|
Boost : |
Subject: [boost] [Opaque] Request for interest in Opaque typedefs library emulation
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2010-05-06 13:07:23
Hi,
I have started to play with a class to define opaque typedefs on funcdamental types. It is based on the C++ proposal "
Progress toward Opaque Typedefs for C++0X" by Walter E. Brown
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1891.pdf
and http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1706.pdf
Please take a look on the preceding links to understand the motivation.
Boost.Sericalization provide a BOOST_STRONG_TYPEDEF already, but in my opinon the implementation is not complete,as only the order operators are defined (But maybe I'm wrong).
Evidently it can not provide everything we can have with a language approach, but IMO this could yet be useful.
The library include two class templates (CRTP) to define opaque types:
* public_opaque_type<OT,UT> : implicit conversion from OT to UT
* private_opaque_type<OT,UT> : no conversion from OT to UT
An opaque type (OT) is a new type, different from the underlying type (UT) and other OT. It defines explicit constructor from the UT, and defines all the operators the UT support but this time applied to the OT.
To define a new OT with this mixin classes
struct serial_number: public_opaque_type<serial_number, unsigned>
{
BOOST_OPAQUE_PUPLIC_FORWARD_CONSTRUCTORS(serial_number,unsigned);
};
struct game_score: private_opaque_type<game_score, unsigned>
{
BOOST_OPAQUE_PRIVATE_FORWARD_CONSTRUCTORS(game_score,unsigned);
};
In addition, defines macros that make this simpler
BOOST_OPAQUE_PUBLIC_TYPEDEF(unsigned, serial_number);
BOOST_OPAQUE_PRIVATE_TYPEDEF(unsigned, game_score);
Next follows the definition of the public_opaque_type
template <typename Final, typename T>
class public_opaque_type
: boost::totally_ordered< Final
, boost::integer_arithmetic< Final
, boost::bitwise< Final
, boost::unit_steppable< Final
, boost::totally_ordered< T, Final // public specific conversions
, boost::integer_arithmetic< T, Final // public specific conversions
, boost::bitwise< T, Final // public specific conversions
> > > > > > >
{
protected:
T val_;
typedef public_opaque_type opaque_type;
public:
typedef T underlying_type;
explicit public_opaque_type(const T v)
: val_(v) {};
public_opaque_type() {};
public_opaque_type(const opaque_type & rhs)
: val_(rhs.val_) {}
public_opaque_type & operator=(const opaque_type & rhs) {
val_ = rhs.val_; return *this;
}
public_opaque_type & operator=(const T rhs) {
val_ = rhs; return *this;
}
T const& underlying() const {
return val_;
}
T& underlying() {
return val_;
}
operator const T & () const {
return val_;
}
operator T & () {
return val_;
}
#if 0
bool operator==(const opaque_type & rhs) const {
return val_ == rhs.val_;
}
#endif
bool operator<(const Final & rhs) const {
return val_ < rhs.val_;
}
Final& operator+=(const Final & rhs) {
val_ += rhs.val_;
return static_cast<Final&>(*this);
}
Final& operator-=(const Final & rhs) {
val_ -= rhs.val_;
return static_cast<Final&>(*this);
}
...
};
I have started to make some tests and it works well for the moment.
Limitations:
* As we can not specialize the behaviour of static_cast/dynamic_cast the library sould provide two specific casts opaque_static_cast and opaque_dynamic_static_cast (Not yet implemented).
* As operator.() can not be overloaded, it works transparently only for underlying types that don't defines member functions (C++ fundamental types, as int, char, ...). For the others an explicit use of the underlying() member function is needed :(
* Others I have not catched yet :(
Do you think it is worth continuing?
Please, let me know if you see a error on the design.
_____________________
Vicente Juan Botet Escribá
http://viboes.blogspot.com/
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk