如何强类型定义非基本类型?

时间:2014-04-21 22:35:42

标签: c++ c++11 boost types typedef

观察以下程序,其中函数接受期望类型和任何类型的typedef类型。

//a user defined type
class Widget{};

//a function that takes a Widget
void function (Widget w){}

int main(){

    //make a typedef (this is C++11 syntax for a typedef. It's the same thing)
    using Gadget = Widget;

    //make the two "different types" (well.. they're not really different as you will see)
    Widget w;
    Gadget g;

    //call a function that should ONLY accept Widgets
    function(w); //works (good)
    function(g); //<- works (I do not want this to compile though)

}

如您所见,typedef实际上并不区分新类型。我反而想继承类型:

//inherit instead
class Gadget: public Widget{};

//make the two "different types"
Widget w;
Gadget g;

//call the function that should ONLY accept widgets
function(w); //works (good)
function(g); //<- works (I do not want this to compile though)

同样的问题 看看提升,我想尝试一个强大的typedef:

#include <boost/serialization/strong_typedef.hpp>

//a user defined type
class Widget{};

//a function that takes the user defined type
void function (Widget w){}

int main(){

    //try to strongly typedef
    BOOST_STRONG_TYPEDEF(Widget, Gadget)

    //make the two "different types"
    Widget w;
    Gadget g;

    //call the function that should ONLY accept widgets
    function(w);
    function(g);

}

编译错误:

In member function ‘bool main()::Gadget::operator==(const main()::Gadget&) const’:
error: no match for ‘operator==’ (operand types are ‘const Widget’ and ‘const Widget’)
  BOOST_STRONG_TYPEDEF(Widget, Gadget)
  ^
In member function ‘bool main()::Gadget::operator<(const main()::Gadget&) const’:
error: no match for ‘operator<’ (operand types are ‘const Widget’ and ‘const Widget’)
  BOOST_STRONG_TYPEDEF(Widget, Gadget)
  ^

显然BOOST_STRONG_TYPEDEF仅适用于基元类型 我试图再次继承,但停止隐式转换:

//I want the functionality, but these are NOT the same type!
class Gadget: public Widget{
    operator Widget() = delete;
};

这也不起作用。

问题:

  1. 为什么boost strong_typedef只适用于原始类型?
  2. 我怎样才能&#39; typedef&#39;一个非原始类型,以获得类似于boost strong_typef?
  3. 的功能

3 个答案:

答案 0 :(得分:5)

基本上你需要两个具有相同行为的无关类。我会使用参数化模板:

template<int tag> class WidgetGadget { ... };
typedef WidgetGadget<0> Widget;
typedef WidgetGadget<1> Gadget;

答案 1 :(得分:3)

BOOST_STRONG_TYPEDEF实际上假定类型是等同的(==),可分配的(=)和不可比的(<)。

如果您的类型不是,那么宏会导致代码无法编译,正如您所见。您可以滚动自己的宏或提供所需操作的实现。

您可以在2012年februari的回答中找到CUSTOM_STRONG_TYPEDEF How to use comparison operators on variant with contained types? ,明确避免获取默认比较行为

更新让您的用例更加明确,查看Live On Coliru

//a user defined type
class Widget{};
class Frobnicator{};

/////////////////////////////////////////////////////
// copied and reduced from boost/strong_typedef.hpp
#define CUSTOM_STRONG_TYPEDEF(T, D)                                 \
struct D                                                            \
    /*: boost::totally_ordered1< D           */                     \
    /*, boost::totally_ordered2< D, T        */                     \
    /*> >                                    */                     \
{                                                                   \
    T t;                                                            \
    explicit D(const T t_) : t(t_) {};                              \
    D(){};                                                          \
    D(const D & t_) : t(t_.t){}                                     \
    D & operator=(const D & rhs) { t = rhs.t; return *this;}        \
    D & operator=(const T & rhs) { t = rhs; return *this;}          \
    explicit operator const T & () const {return t; }               \
    explicit operator T & () { return t; }                          \
    /*bool operator==(const D & rhs) const { return t == rhs.t; } */\
    /*bool operator<(const D & rhs) const { return t < rhs.t; }   */\
};

CUSTOM_STRONG_TYPEDEF(Widget, Gadget)
CUSTOM_STRONG_TYPEDEF(Frobnicator, Normalcy)

void acceptWidget(Widget){}
void acceptGadget(Gadget){}
void acceptFrobnicator(Frobnicator){}
void acceptNormalcy(Normalcy){}

int main(){

    //make the two "different types" (well.. they're not really different as you will see)
    Widget w;
    Gadget g;

    //call a function that should ONLY accept Widgets
    acceptWidget(w); //works (good)
    acceptGadget(g);

    //acceptWidget(g); // Error
    //acceptGadget(w); // Error
    // but we can enjoy conversions if we summon them
    acceptWidget(static_cast<Widget&>(g));

    Frobnicator f;
    Normalcy n;
    acceptFrobnicator(f);
    acceptNormalcy(n);

}

答案 2 :(得分:1)

也许你可以使用私有继承和一些using s?

class Gadget : Widget { using Widget::Widget; using Widget::foo; ... };