Namespace in a typedef

B

balor

Sometimes it is useful to assign class names to types that are
primitives even if they add no more functionality, at the very least to
be able to determine which constants apply to a type:

typedef int Address;
void test(Address address) { ... }
const Address ADDRESS1 = 0xff, ADDRESS2 = 0x3f;

Of course, this method is type unsafe since any int can be passed in
but to the reader it is at least clear that ADDRESS1 and ADDRESS2 are
associated with argument 1 in function test(). The alternative, more
typesafe way is to:

class Address {
public:
operator=(int address) ...
operator int() ...
.. all other operators

static const Address ADDRESS1, ADDRESS2;
private:
Address(int address) ...
};

This creates an enumeration that can behave as an integer. If the items
in the enum don't need actual values, then one can just compare the
address of the items for identity. To be even more safe, replace the
casting operator with a method. Unfortunately, this method works much
better in Java than in C++ as the constants must be defined in a
separate file, a large list of functions must be overloaded, and
remembering to compare by address is painful. This implementation is
also too large for a realtime system with memory constraints. GCC is
also nice enough to print a warning that it has no public constructors.

So my question is, I like the method 1 for creating a type but I have
no good place to put the constants for it and was wondering if anyone
had any ideas. What I'm looking for is something like:

class Address : public int {
// constants
};

Of course this doesn't work. I thought maybe something like this would
work:

typedef int Address;
namespace Address { // constants }

But unfortunately it doesn't. Any ideas on how to accomplish this?
 
M

msalters

balor said:
Sometimes it is useful to assign class names to types that are
primitives even if they add no more functionality, at the very least to
be able to determine which constants apply to a type:

typedef int Address;
void test(Address address) { ... }
const Address ADDRESS1 = 0xff, ADDRESS2 = 0x3f;

Of course, this method is type unsafe since any int can be passed in
but to the reader it is at least clear that ADDRESS1 and ADDRESS2 are
associated with argument 1 in function test().
The alternative, more typesafe way is to:

.... use enums, but you can also use ...
class Address {
public:
operator=(int address) ...
operator int() ...
.. all other operators

static const Address ADDRESS1, ADDRESS2;
private:
Address(int address) ...
};

This creates an enumeration that can behave as an integer.
If the items in the enum don't need actual values, then
one can just compare the address of the items for identity.
To be even more safe, replace the casting operator with
a method. Unfortunately, this method works much
better in Java than in C++ as the constants must be
defined in a separate file, a large list of functions
must be overloaded, and remembering to compare by address
is painful.
"Remembering to compare by address"? What's stopping you
from providing a sane operator==? At the very least it can
return this==&rhs, or else it can do o normal value comparison.
This implementation is also too large for a realtime
system with memory constraints.

FUD. There is no reason at all why it would generate more
code. Everything can be inlined, producing identical
assembly.
In fact, because of typesafety, a good compiler could
even detect the range of possible values and generate
more efficient code.

Regards,
Michiel Salters
 
B

balor

I'd use enums if namespace weren't problematic.

enum A {A1, A2};
void function() { A a = A::A1; }

Unfortunately, A1 and A2 are defined in the global namespace and one is
not allowed to scope into A. One could try:

namespace A {
enum {A1, A2};
}

This method works but then A1/A2 don't have a type. Another solution
is:

namespace A {
enum B {A1, A2};
}

This last method works but the type requires a scope which adds no
value. I don't understand why the standard defines constants in the
namespace of the enum.

Even if I had an enum that didn't pollute its namespace, there are
other concerns. The enum isn't type safe like a class nor expandable
like one, although one could convert it to a class without affecting
existing code.

On the other issue, it is true if functions were inlined in the
class-based enum the functions would take no space but what about
constants? There has to be a location in memory allocated to compare by
address whereas with a static const int the compiler can inline the int
everywhere it is used. I suppose the amount of memory consumed by
constants is trivial but the amount of code required to define the type
is rather large. Perhaps I shouldn't be defining classes that behave as
integers in the first place.

I can see how type safety improves documenting of code and reduces bugs
but how would a compiler exploit type safety to produce more efficient
code?

Thanks for the help.
 
B

balor

One thing I just thought of that has promise is:

class A {
public:
operator int() { return (int)this; }
static const A a, b;
};

const A A::a;
const A A::b;

Unfortunately, GCC requires that variables be initialized. I fail to
see the value in this requirement as the address of the object alone is
all that I'm interested in. The following works though:

const A A::a(a);
const A A::b(b);

Its a stupid workaround though.
 

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,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top