[英]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;
};
那也行不通。
問題:
基本上你需要兩個具有相同行為的無關類。 我會使用參數化模板:
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.