Two proxy classes in main class

N

Nephi Immortal

I created two private proxy classes and I put them into one main
class. I use two functions Low_Byte() and High_Byte() to modify main
class’ data member through reference and Word() through pointer.
C++ Compiler complied without any problems. If I declare constant,
then C++ Compiler will give you an error message.
How can I add const function? I struggle while I am trying to figure
for couple hours.

class _16_Bits {
private:
typedef unsigned int size;

class _Low_Byte {
public:
_Low_Byte( size &byte ) : m_data( byte ) {}
~_Low_Byte() {}

_Low_Byte &operator= ( const size &byte ) {
m_data &= 0xFF00;
m_data |= byte & 0xFF;
return *this;
}

operator size () { return m_data & 0xFF; }
operator size () const { return m_data & 0xFF; }

private:
size &m_data;
};

class _High_Byte {
public:
_High_Byte( size &byte ) : m_data( byte ) {}
~_High_Byte() {}

_High_Byte &operator= ( const size &byte ) {
m_data &= 0xFF;
m_data |= ( byte & 0xFF ) << 8;
return *this;
}

operator size () { return ( m_data >> 8 ) & 0xFF; }
operator size () const { return ( m_data >> 8 ) & 0xFF; }

private:
size &m_data;
};

public:
explicit _16_Bits( size word ) : m_data( word ) {}
~_16_Bits() {}

_16_Bits &operator= ( size word ) {
m_data = word & 0xFFFF;
return *this;
}

_Low_Byte Low_Byte() { return _Low_Byte( m_data ); }
_High_Byte High_Byte() { return _High_Byte( m_data ); }
_16_Bits &Word() { return *this; }

operator size () { return m_data; }
operator size () const { return m_data; }

private:
size m_data;
};



int main () {
_16_Bits W( 0x1234 );

W.Low_Byte() = 0x5A;
W.High_Byte() = 0x7C;

unsigned int L = W.Low_Byte();
unsigned int H = W.High_Byte();

W.Word() = 0xABCD;
unsigned int W2 = W;

const _16_Bits V( 0x1234 );


unsigned int L2 = V.Low_Byte(); // error
unsigned int H2 = V.High_Byte(); // error

unsigned int V2 = V;

return 0;
}
 
B

Bart van Ingen Schenau

Nephi said:
I created two private proxy classes and I put them into one
main
class. I use two functions Low_Byte() and High_Byte() to modify
main
class’ data member through reference and Word() through
pointer.
C++ Compiler complied without any problems. If I declare
constant,
then C++ Compiler will give you an error
message.
How can I add const function? I struggle while I am trying to
figure
for couple hours.

The clean solution is to create two additional (nested) helper-classes
_16_Bits::_Low_Byte_const and _16_Bits::_High_Byte_const, which give
read-only access to the data similar to the existing _16_Bits::_Low_Byte and
_16_Bits::_High_Byte.

Then you can declare the const functions as

_Low_Byte_const Low_Byte() const { return _Low_Byte_const( m_data ); }
_High_Byte_const High_Byte() const { return _High_Byte_const( m_data ); }


Another option is to add the following constructors to _Low_Byte (and
similar for _High_Byte):

_Low_Byte( const size& byte) : m_data(const_cast<size&>(byte) {}

Then you can declare the const functions as

_Low_Byte const Low_Byte() const { return _Low_Byte( m_data ); }

technically, the const_cast in the constructor can lead to UB, but by
returning a const-qualified object, the UB is averted because it still
remains impossible to modify a const object.

<snip - code>

Bart v Ingen Schenau
 
N

Nephi Immortal

The clean solution is to create two additional (nested) helper-classes
_16_Bits::_Low_Byte_const and _16_Bits::_High_Byte_const, which give
read-only access to the data similar to the existing _16_Bits::_Low_Byte and
_16_Bits::_High_Byte.

Then you can declare the const functions as

  _Low_Byte_const Low_Byte() const { return _Low_Byte_const( m_data ); }
  _High_Byte_const High_Byte() const { return _High_Byte_const( m_data ); }

Another option is to add the following constructors to _Low_Byte (and
similar for _High_Byte):

  _Low_Byte( const size& byte) : m_data(const_cast<size&>(byte) {}

Then you can declare the const functions as

  _Low_Byte const Low_Byte() const { return _Low_Byte( m_data ); }

technically, the const_cast in the constructor can lead to UB, but by
returning a const-qualified object, the UB is averted because it still
remains impossible to modify a const object.

You suggested two non-constant class helpers and other two constant
class helpers into one main class. It is the only best option to
avoid constness_cast keyword due to undefined behavior.
I use the option as you suggested. However, Low_Byte_Const class has
operator=. C++ Compiler will compile without any problems since
m_data is supposed to be read-only. How can C++ Compiler reports an
error as saying left value is declared constant rather than cannot
access to private operator=?
Perhaps, you suggest to use private keyword and do not worry the non-
message as saying constant left value.

class _Low_Byte_Const {
public:
_Low_Byte_Const( const size &byte ) : m_data( byte ) {}
~_Low_Byte_Const() {}

_Low_Byte_Const &operator= ( const _Low_Byte_Const &right ) {
// size temp_data = right.m_data;
return *this; }

// operator size () { return m_data & 0xFF; }
operator size () const { return m_data & 0xFF; }

//private: /* supoose to be uncommented */
_Low_Byte_Const &operator= ( const size &byte ) {
byte; // ignore level 4 warning
// m_data &= 0xFF00;
// m_data |= byte & 0xFF;
return *this;
}

private:
const size m_data;
};

Do I need to declare reference ‘&’ between ‘const size’ and ‘byte’ in
operator= since it is only one value. The error message will report
as saying cannot convert from size & to size because the value may be
non-reference.

Example:

size value = 0x7A;
w.Low_Byte() = 0x4C; // pass by copy value
w.Low_Byte() = value; // pass by reference

The main class can be either non-constant or constant. If I choose
to declare constant, am I required to create two copies of member
functions on each pair of member functions.

For example:
void Print_Hex() { /* your code */ }
void Print_Hex() const { /* your code */ }

void Print_Dec() { /* your code */ }
void Print_Dec() const { /* your code */ }

void Print_Bin() { /* your code */ }
void Print_Bin() const { /* your code */ }

etc….

The same code in function body can waste source code’s space because
of twice duplication. Perhaps, you suggest – declare and define
global function as Print_String() before class definition and then
pair of Print_Hex(), Print_Dec(), and Print_Bin() are either non-
constant or constant will call non-constant global function
Print_String().
 
B

Bart van Ingen Schenau

Nephi said:
object.

You suggested two non-constant class helpers and other two
constant
class helpers into one main class. It is the only best option
to
avoid constness_cast keyword due to undefined
behavior.
I use the option as you suggested. However, Low_Byte_Const class
has operator=.

Why? What good is it to declare an operator= on a class that is not supposed
to support assignment?
C++ Compiler will compile without any problems since
m_data is supposed to be read-only. How can C++ Compiler reports
an
error as saying left value is declared constant rather than
cannot
access to private
operator=?
Perhaps, you suggest to use private keyword and do not worry the
non-
message as saying constant left
value.

class _Low_Byte_Const
{
public:
_Low_Byte_Const( const size &byte ) : m_data( byte )
{}
~_Low_Byte_Const()
{}

_Low_Byte_Const &operator= ( const _Low_Byte_Const &right )
{
// size temp_data =
right.m_data;
return *this;
}
This operator= should be left out completely. As _Low_Byte_Const has a
reference-type member (m_data), the compiler will not be able to generate an
operator= and that is exactly the behaviour you want.
// operator size () { return m_data & 0xFF;
}
operator size () const { return m_data & 0xFF;
}

//private: /* supoose to be uncommented
*/
_Low_Byte_Const &operator= ( const size &byte )
{
byte; // ignore level 4
warning
// m_data &=
0xFF00;
// m_data |= byte &
0xFF;
return
*this;

}
This operator= should be left out as well. You don't want to support
assignment of an integer, so you should not provide any operators that would
be used in such an assignment.
private:
const size
m_data;
};
The main class can be either non-constant or constant. If I
choose
to declare constant, am I required to create two copies of
member
functions on each pair of member
functions.

No. If the function itself does not modify *this and is also does not pass
pointers or references to other functions that might cause modification of
*this, then it is sufficient to have only one, const-qualified, function.
This function can be used both by const and non-const objects.

Bart v Ingen Schenau
 

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

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top