Archived

This topic is now archived and is closed to further replies.

creating different 'int's

This topic is 5148 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I would like to use the same type, unsinged int, for two different things. Is there way to make the compiler complain when the usages are being mixed? My situation is as follows: I am devising a simple user interface for text-consoles. The interface returns handles for output fields, as well as for eventHandlers. I don''t need anything but a simple integer to identify those handles but I''d prefer that a handle returned for an output field can''t be used in the context of event handling. What I tried:
typedef unsigned int UIhandle;
typedef unsigned int UIevent;
doesn''t yield the desired incompatibility between UIhandle and UIevent Is there any way to achieve that? Maybe along the lines of anynomous structs, or something like it. --------------------------- I may be getting older, but I refuse to grow up

Share this post


Link to post
Share on other sites
typedef just makes an alias.. hence internally, they are the same type. If any function could only want a specific one.. then make them into structs, and require that specific type. If you are in a situation where you could need one, or other, or both to be accepted, then inherit them both from a common base (UIBase or something)... then if you want to take either, have a base type as a parameter... if you want a specific one... require one of these two derived types.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You could have different enums; they''ll map to int anyway but the compiler will yell for sure. Just specify the default (zero) element and make sure you typecast in the implementation to turn off compiler warnings. If you need the implementation to distinguish the two at runtime (not just compiler warnings), you could use the upper 8 or 16 bits to plug some sort of unique identifier; they are easily masked out. Similarly, you don''t need to start indexing at 0; the 0th element could start at index 0xDEADBEEFL so every operation would have to subtract out the per-type offset and check for boundaries.

Share this post


Link to post
Share on other sites
I found this a time ago, I''m posting the whole thing.
Hello,

It seems that every once in a while, someone mentions that
C++ is missing a "strong typedef" facility.

This briefly-tested macro/template combination emulates
a simplified version of such a facility. Maybe some of
you will find it interesting to play with.

I only tested it on an older compiler (g++ 2.96) so
hopefully it doesn''t implode on the newer ones.

The funny thing is, after I played around with strong
typedefs for a while, they didn''t seem as wonderful
as I originally thought they would be. Maybe that''s
why C++ didn''t have them in the first place!

USAGE:
To create strong typedefs of "float" named
"velocity_t" and "distance_t", you would call

STRONG_TYPEDEF(float, velocity_t);
STRONG_TYPEDEF(float, distance_t);

The types "velocity_t" and "distance_t" will behave mostly
like floats, and will be initializable from floats, but
will not be interchangable. For example, the following
code will be legal:

distance_t a=10;
distance_t b=20;
a += b;

But the following code will not:

distance_t a=10;
velocity_t b=20;
a += b;

To convert between the two, you have to access the .value member
like so:

distance_t a=10;
velocity_t b=20;
a += b.value;

Derek Ross

==== Source File ===============================
/*

Notes about the STRONG_TYPEDEF macro.

Usage:
STRONG_TYPEDEF(original_type, name_of_typedef);

Example:
STRONG_TYPEDEF(double, dollars_t);

STRONG_TYPEDEF creates a template type that is basically
a wrapper around a built-in type such as int or double.
Most of the operators are overloaded to operate on the
wrapped variable.

Casting to the original type is not automatic.
To get to the wrapped variable, access the ".value"
member.

STRONG_TYPEDEF cannot be used to define a typedef
within a function, only globally.

This was tested with g++ 2.96.

*/


#include <iostream>
#include <utility>
#include <vector>
#include <algorithm>
#include <string>
#include <cmath>

#define MAKE_STRONG_TYPEDEF_OP_CONST(rettype, op)\
rettype operator op \
(const strong_typedef_class<T,Unique_T>& r) \
const\
{\
return rettype(value op r.value);\
}\
rettype operator op (const T& r) const\
{\
return rettype(value op r);\
}

#define MAKE_STRONG_TYPEDEF_OP_ASSIGN(op)\
strong_typedef_class<T,Unique_T>& operator op \
(const strong_typedef_class<T,Unique_T>& r) \
{\
value op r.value;\
return *this;\
}\
strong_typedef_class<T,Unique_T>& operator op \
(const T& r) \
{\
value op r;\
return *this;\
}

#define MAKE_STRONG_TYPEDEF_UNOP(op)\
T operator op () const\
{\
return op value;\
}


template< class T, class Unique_T>
struct strong_typedef_class {
typedef T value_type;
typedef strong_typedef_class<T,Unique_T> self_type;
T value;
strong_typedef_class()
:value(T())
{}

strong_typedef_class(const T& v)
:value(v)
{}

strong_typedef_class(const strong_typedef_class& v)
:value(v.value)
{}

strong_typedef_class& operator=(const T&v)
{
value=T(v);
return *this;
}
strong_typedef_class& operator=(const strong_typedef_class& v)
{
value=T(v.value);
return *this;
}

/*
operator T&()
{
return value;
}
*/


MAKE_STRONG_TYPEDEF_OP_CONST(bool, > )
MAKE_STRONG_TYPEDEF_OP_CONST(bool, < )
MAKE_STRONG_TYPEDEF_OP_CONST(bool, >= )
MAKE_STRONG_TYPEDEF_OP_CONST(bool, <= )
MAKE_STRONG_TYPEDEF_OP_CONST(bool, == )
MAKE_STRONG_TYPEDEF_OP_CONST(bool, != )
MAKE_STRONG_TYPEDEF_OP_CONST(bool, && )
MAKE_STRONG_TYPEDEF_OP_CONST(bool, || )

MAKE_STRONG_TYPEDEF_OP_CONST(self_type, +)
MAKE_STRONG_TYPEDEF_OP_CONST(self_type, -)
MAKE_STRONG_TYPEDEF_OP_CONST(self_type, /)
MAKE_STRONG_TYPEDEF_OP_CONST(self_type, *)
MAKE_STRONG_TYPEDEF_OP_CONST(self_type, %)
MAKE_STRONG_TYPEDEF_OP_CONST(self_type, <<)
MAKE_STRONG_TYPEDEF_OP_CONST(self_type, >>)
MAKE_STRONG_TYPEDEF_OP_CONST(self_type, &)
MAKE_STRONG_TYPEDEF_OP_CONST(self_type, |)
MAKE_STRONG_TYPEDEF_OP_CONST(self_type, ^)

MAKE_STRONG_TYPEDEF_OP_ASSIGN( += )
MAKE_STRONG_TYPEDEF_OP_ASSIGN( -= )
MAKE_STRONG_TYPEDEF_OP_ASSIGN( *= )
MAKE_STRONG_TYPEDEF_OP_ASSIGN( /= )
MAKE_STRONG_TYPEDEF_OP_ASSIGN( >>= )
MAKE_STRONG_TYPEDEF_OP_ASSIGN( <<= )
MAKE_STRONG_TYPEDEF_OP_ASSIGN( ^= )
MAKE_STRONG_TYPEDEF_OP_ASSIGN( &= )
MAKE_STRONG_TYPEDEF_OP_ASSIGN( |= )
MAKE_STRONG_TYPEDEF_OP_ASSIGN( %= )

MAKE_STRONG_TYPEDEF_UNOP(+)
MAKE_STRONG_TYPEDEF_UNOP(-)
MAKE_STRONG_TYPEDEF_UNOP(~)
MAKE_STRONG_TYPEDEF_UNOP(!)

strong_typedef_class<T,Unique_T>& operator ++ ()
{
++value;
return *this;
}

strong_typedef_class<T,Unique_T>& operator -- ()
{
--value;
return *this;
}

strong_typedef_class<T,Unique_T>& operator ++ (int)
{
++value;
return *this;
}

strong_typedef_class<T,Unique_T>& operator -- (int)
{
--value;
return *this;
}
};

template<class T, class Unique_T>
std::ostream& operator<<(std::ostream& os, const
strong_typedef_class<T,Unique_T>& r)
{
os << r.value;
return os;
}

template<class T, class Unique_T>
std::istream& operator>>(std::istream& is,
strong_typedef_class<T,Unique_T>& r)
{
is >> r.value;
return is;
}

#define STRONG_TYPEDEF(base_type, typedef_name)\
struct uniq_clas_for_strng_typdf__ ## typedef_name {};\
typedef strong_typedef_class<base_type, \
uniq_clas_for_strng_typdf__ ## typedef_name > \
typedef_name;


/////////////////// EXAMPLE /////////////////////


STRONG_TYPEDEF(double, volts_st);
STRONG_TYPEDEF(double, amps_st);
STRONG_TYPEDEF(double, ohms_st);
STRONG_TYPEDEF(double, watts_st);

watts_st GetWatts(volts_st v, amps_st a)
{
return v.value * a.value;
}

watts_st GetWatts(amps_st a, ohms_st o)
{
return a.value * a.value * o.value;
}

watts_st GetWatts(volts_st v, ohms_st o)
{
return v.value * v.value / o.value;
}

#define PRINT(var) {std::cout<<#var<<": "<<var<<std::endl;}

int main()
{
volts_st v = 12.0;
amps_st a = 5.99;
ohms_st o = 2.01;

PRINT( v );
PRINT( a );
PRINT( o );
PRINT( GetWatts(v,a) );
PRINT( GetWatts(a,o) );
PRINT( GetWatts(v,o) );

// have to access ".value"

// to convert to double.

PRINT( sqrt(v.value) );

// next lines should give compiler errors:

// std::cout << GetWatts(o,v) << std::endl;

// v = a;


}


[How To Ask Questions|STL Programmer''s Guide|Bjarne FAQ|C++ FAQ Lite|C++ Reference|MSDN]

Share this post


Link to post
Share on other sites
typedef will not conflict...if you are using C++ you may use typedef in your class def and make them visible inside.



class MyClass
{
public:

typedef unsigned int MYTYPE;

};



you can access MYTYPE by ::


MyClass::MYTYPE myvariable = 0;


or typedef it again in another class



class SecondClass
{
public:

typedef MyClass::MYTYPE MYTYPE;

};



and so on.

You can also use the 'unknown' namespace directive (it works in C too).






[edited by - blizzard999 on November 6, 2003 6:50:01 PM]

Share this post


Link to post
Share on other sites
I just want to point out that in the code dalleboy posted, the post increment/decrement operators do not appear to be correctly defined, so you might want to proofread the rest of it to make sure its all correct.

Share this post


Link to post
Share on other sites