invalid static_cast problem

F

fjansen

I'm trying to understand the underlying issue in my code that is
generating the following compile-time error message:

SingleLevelLogicalUnitNumber.cpp: In member function `bool
scsi::SingleLevelLogicalUnitNumber::invariant() const':
SingleLevelLogicalUnitNumber.cpp:37: error: invalid static_cast from
type `scsi::LogicalUnitAddressingField' to type `const
scsi::peripheralDeviceAddress&'

The code section in question is the following:

bool SingleLevelLogicalUnitNumber::invariant() const {

bool level0Ok = false;

LogicalUnitAddressingField::Method addressMethod =
getAddress(0).getMethod();

if (LogicalUnitAddressingField::peripheralDevice == addressMethod)
{

const PeripheralDeviceAddress & theAddress = static_cast<const
PeripheralDeviceAddress &>( getAddress(0) );

if (theAddress.getBusIdentifier() == 0 ) {

level0Ok = true;

}

} else if (LogicalUnitAddressingField::FlatSpace == addressMethod)
{

level0Ok = true;

} // else it's a violation of the class invariant to have any
other address method.



bool levels123Ok = MemIsZero( &myData[2], 6 );



return level0Ok && levels123Ok;

}


LogicalUnitAddressingField is a base class (non-virtual) for
PeripheralDeviceAddress (see class definitions below) and I would
expect that this cast would be legal; what am I missing here?

Thanks,

Frank


#ifndef SCSI_LOGICALUNITADDRESSINGFIELD_H

#define SCSI_LOGICALUNITADDRESSINGFIELD_H 1



#include "services/dbc.h"


#include <stdint.h>

#ifdef __GNUC__

#if __GNUCC < 3

#include <iostream>

#else

#include <ostream>

#endif

#else // there are other compilers, right?

#include <ostream>

#endif // __GNUC__



namespace scsi {

class LogicalUnitAddressingField {

public:

enum Method {

LogicalUnit = 2, // Logical unit addressing method

PeripheralDevice = 0, // Peripheral device addressing method

FlatSpace = 1, // Flat space addressing method

ExtendedLogicalUnit = 3 // Extended logical unit addressing
method

};


/**

* Construct a default logical unit addressing field.

*/

LogicalUnitAddressingField() {

myAddress[0] = '\0';

myAddress[1] = '\0';

}


/**

* Construct a logical unit addressing field.

*/

LogicalUnitAddressingField( Method itsAddressMethod, unsigned int
itsMethodSpecificAddress ) {

myAddress[0] = static_cast<uint8_t>( (itsAddressMethod << 6) |
((itsMethodSpecificAddress >> 8) & 0x3f) );

myAddress[1] = static_cast<uint8_t>( itsMethodSpecificAddress
& 0xff );

REQUIRE( itsMethodSpecificAddress <= 0x3fff );

}


/**

* Construct a logical unit addressing field from two bytes of
data.

*/

LogicalUnitAddressingField( const uint8_t * itsData ) {

myAddress[0] = itsData[0];

myAddress[1] = itsData[1];

}


/**

* Destroy a logical unit addressing field.

* @preconditions invariant()

*/

~LogicalUnitAddressingField() {}



#ifndef NDEBUG

/**

* Class invariant

*/

bool invariant() const;

#endif // NDEBUG


/**

* Return my addressing method.

*/

Method getMethod() const {

return static_cast<Method>( (myAddress[0] >> 6) & 0x03 );

}


/**

* Return my data.

*/

const uint8_t * getData() const {

return myAddress;

}


/**

* Print the address field on the supplied ostream.

*/

void printOn( std::eek:stream & os ) const;



protected:

/**

* My address.

*/

uint8_t myAddress[2];

};



} // namespace scsi



#endif // SCSI_LOGICALUNITADDRESSINGFIELD_H




#ifndef SCSI_PERIPHERALDEVICEADDRESS_H

#define SCSI_PERIPHERALDEVICEADDRESS_H 1



#include "LogicalUnitAddressingField.h"



#include "services/dbc.h"



namespace scsi {



class PeripheralDeviceAddress : public LogicalUnitAddressingField {

public:

/**

* Construct a default peripheral device address.

* The default addresses LUN 0.

*/

PeripheralDeviceAddress()

: LogicalUnitAddressingField( PeripheralDevice, 0 )

{}



/**

* Construct a peripheral device address.

*/

PeripheralDeviceAddress( unsigned int itsBusIdentifier, unsigned
int itsTargetOrLun )

: LogicalUnitAddressingField( PeripheralDevice,
(itsBusIdentifier << 8) | itsTargetOrLun )

{

REQUIRE( (itsBusIdentifier < 64) && (itsTargetOrLun < 256) );

}



/**

* Destroy a peripheral device address.

* @preconditions invariant()

*/

~PeripheralDeviceAddress() {}



#ifndef NDEBUG

/**

* Class invariant

*/

bool invariant() const;

#endif // NDEBUG



/**

* Return my bus identifier.

*/

unsigned int getBusIdentifer() const {

return myAddress[0] & 0x3f;

}




};



} // namespace scsi



#endif // SCSI_PERIPHERALDEVICEADDRESS_H
 
M

Markus Moll

Hi

I'm trying to understand the underlying issue in my code that is
generating the following compile-time error message:

SingleLevelLogicalUnitNumber.cpp: In member function `bool
scsi::SingleLevelLogicalUnitNumber::invariant() const':
SingleLevelLogicalUnitNumber.cpp:37: error: invalid static_cast from
type `scsi::LogicalUnitAddressingField' to type `const
scsi::peripheralDeviceAddress&'

The code section in question is the following: [...]
const PeripheralDeviceAddress & theAddress = static_cast<const
PeripheralDeviceAddress &>( getAddress(0) );

The question is what the declaration of "getAddress" looks like. My guess
would be that it's:
LogicalUnitAddressingField getAddress(int/unsigned/std::size_t i)

In that case:
1. getAddress(0) is an rvalue
2. getAddress(0) is not a PeripheralDeviceAddress

1. makes the compiler complain, 2. tells you why you shouldn't even try.

Could you post the declaration of getAddress, as this is only a guess?

Markus
 
F

fjansen

Markus,

thank you for the reply; should have included that in the first
place. getAddress is declared as follows:

class EightByteLogicalUnitNumber : public LogicalUnitNumber {
public:
/**
* Construct a default eight-byte logical unit number.
*/
EightByteLogicalUnitNumber() {
std::memset( myData, '\0', sizeof( myData ) );
}

/**
* Return the specified address field.
*/
LogicalUnitAddressingField getAddress( int index ) const {
REQUIRE( (index >= 0) && (index < 4) );
return LogicalUnitAddressingField( &(myData[ index * 2 ]) );
}

Thank you,

Frank
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,262
Messages
2,571,051
Members
48,769
Latest member
Clifft

Latest Threads

Top