![](/img/trans.png)
[英]How to template specialize a function based on member variable existence
[英]Choose template function based on existence of member
假設你有這兩個類:
class A
{
public:
int a;
int b;
}
class B
{
public:
int a;
int b;
}
class C
{
public:
float a1;
float b1;
}
enum class Side { A, B };
我想要一個模板函數,它取一個side
和一個T
,並且根據T
,如果類有一個成員T::a
,或者對“ T.a1
”的引用,則返回對“ Ta
”或“ Tb
”的引用。如果類有一個成員T::a1
則為“ T.b1
”。
我的出發點是:
template<typename T>
auto &GetBySide(const Side &side, const T &twoSided)
{
return side == Side::A?twoSided.a:twoSided.b;
}
template<typename T>
auto &GetBySide(const Side &side, const T &twoSided)
{
return side == Side::A?twoSided.a1:twoSided.b1;
}
問題是如果成員a
不存在,如何讓編譯器跳過第一個模板。
所以我實現了下面@ Jarod42給出的解決方案,但它在VS 2015中給出了錯誤,因為VS能夠區分模板。 這是一個解決方法:
template<typename T>
auto GetBySide(const Side &side, const T& twoSided)
-> decltype((twoSided.a))
{
return side == Side::A ? twoSided.a : twoSided.b;
}
// Using comma operator to trick compiler so it doesn't think that this is the same as above
template<typename T>
auto GetBySide(const Side &side, const T &twoSided)
-> decltype((0, twoSided.a1))
{
return side == Side::A ? twoSided.a1 : twoSided.b1;
}
// See comment above
template<typename T>
auto GetBySide(const Side &side, const T &twoSided)
-> decltype((0, 0, twoSided.a2))
{
return side == Side::A ? twoSided.a2 : twoSided.b2;
}
另一種方法是使用逗號運算符和表示每個“概念”的特殊結構
有了SFINAE。
template<typename T>
auto GetBySide(const Side &side, const T& twoSided)
-> decltype((twoSided.a))
{
return side == Side::A ? twoSided.a : twoSided.b;
}
template<typename T>
auto GetBySide(const Side &side, const T &twoSided)
-> decltype((twoSided.a1))
{
return side == Side::A ? twoSided.a1 : twoSided.b1;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.