簡體   English   中英

如何強類型定義非基本類型?

[英]How do I strongly typedef non-primitive types?

請注意以下程序,其中函數接受期望類型和作為該類型的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. 我如何'typedef'非原始類型以獲得類似於boost strong_typef的功能?

基本上你需要兩個具有相同行為的無關類。 我會使用參數化模板:

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

BOOST_STRONG_TYPEDEF實際上假設類型是equatable( == ),assignable( = )和less-than-comparative( < )。

如果您的類型不是,那么宏會導致代碼無法編譯,如您所見。 您可以滾動自己的宏或提供所需操作的實現。

您可以在2012年2月的答案中找到CUSTOM_STRONG_TYPEDEF如何在變量上使用包含類型的比較運算符? ,明確避免獲取默認比較行為

更新使您的用例更加明確, 請參閱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);

}

也許你可以使用私有繼承,有些using s?

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM