根据成员的存在选择模板函数
Choose template function based on existence of member
假设你有这两个 classes:
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
,returns 引用“T.a
" 或 "T.b
" 如果 class 有一个成员 T::a
,或者引用 "T.a1
" 或 "T.b1
" 如果 class 有成员 T::a1
.
我的出发点是:
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;
}
另一种方法是使用逗号运算符和一个表示每个 "concept"
的特殊结构
与 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;
}
假设你有这两个 classes:
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
,returns 引用“T.a
" 或 "T.b
" 如果 class 有一个成员 T::a
,或者引用 "T.a1
" 或 "T.b1
" 如果 class 有成员 T::a1
.
我的出发点是:
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;
}
另一种方法是使用逗号运算符和一个表示每个 "concept"
的特殊结构与 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;
}