c++ - 根据成员的存在选择模板函数

标签 c++ templates sfinae

假设您有这两个类:

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)。

我的出发点是:

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; 
}

Demo

关于c++ - 根据成员的存在选择模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41811817/

相关文章:

c++ - 模板模板参数推导与 sfinae

c++ - [填空]左边必须有类/结构/union 错误

c++ - 在多线程 C++ 应用程序中调试段错误的一些常见方法是什么?

templates - Phoenix : render template of other folder

c++ - SFINAE用于非成员运算符重载

c++ - 如何使用 Application Verifier 查找内存泄漏

c++ - 可变类中的模板函数

c++ - 从模板函数返回默认构造或无效

c++ - SFINAE 编译器问题

c++ - 在 SFINAE 上下文中作为模板模板参数传递的引用类型的别名模板