繁体   English   中英

根据成员的存在选择模板功能

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM