假设你有这两个类:
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.b
"如果类有一个成员T::a
,或参考" T.a1
"或" T.b1
"如果类有一个成员T::a1
.
我的出发点是:
templateauto &GetBySide(const Side &side, const T &twoSided) { return side == Side::A?twoSided.a:twoSided.b; } template auto &GetBySide(const Side &side, const T &twoSided) { return side == Side::A?twoSided.a1:twoSided.b1; }
问题是如果成员a
不存在,如何让编译器跳过第一个模板.
所以我实现了下面@ Jarod42给出的解决方案,但它在VS 2015中给出了错误,因为VS能够区分模板.这是一个解决方法:
templateauto 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 auto GetBySide(const Side &side, const T &twoSided) -> decltype((0, twoSided.a1)) { return side == Side::A ? twoSided.a1 : twoSided.b1; } // See comment above template auto GetBySide(const Side &side, const T &twoSided) -> decltype((0, 0, twoSided.a2)) { return side == Side::A ? twoSided.a2 : twoSided.b2; }
另一种方法是使用逗号运算符和表示每个"概念"的特殊结构
有了SFINAE.
templateauto GetBySide(const Side &side, const T& twoSided) -> decltype((twoSided.a)) { return side == Side::A ? twoSided.a : twoSided.b; } template auto GetBySide(const Side &side, const T &twoSided) -> decltype((twoSided.a1)) { return side == Side::A ? twoSided.a1 : twoSided.b1; }
演示