templates - 如何使用 std::enable_if_t 和 std::is_base_of 来检查 SFINAE 的编译时继承?

标签 templates c++14 sfinae typetraits

我试图在编译时将函数的模板类型限制为特定类及其子类。为此,我使用了类型特征 std::enable_if_tstd::is_base_of ,如下所示:

template <typename T = std::enable_if_t<std::is_base_of<A, T> > >

但是模板仍然使用不属于继承层次结构的类型(即 int )进行编译。以下是问题的 MCVE:
class A {
public:
  A(float a) : a(a) {}
  float a;
};
class B : public A{
public:
  B(float a) : A(a) {}
};

template <typename T = std::enable_if_t<std::is_base_of<A, T> > >
void templateFunction(T a) {

}

int main() {
  templateFunction<A>(A(1.0f)); // OK -> std::is_base_of<A, A>
  templateFunction<B>(B(1.0f)); // OK -> std::is_base_of<A, B>

  templateFunction<int>(1); // Should not compile! int is not a subclass of A -> std::is_base_of<A, int>
  return 0;
}

这在 Visual Studio 2017 下编译没有任何错误,但模板函数的最后实例化在我的理解中不应该编译。
我对类型特征的使用是否有任何问题,或者 Visual Studios SFINAE 实现是否有问题?

最佳答案

您对 enable_if 的使用有点奇怪,我会执行以下操作:

template <typename T>
std::enable_if_t<std::is_base_of<A, T>::value> templateFunction(T a) {

}

或者:
template <typename T>
void templateFunction(std::enable_if_t<std::is_base_of<A, T>::value, T> a) {

}

更好的解决方案:完全忘记 SFINAE:
template <typename T>
void templateFunction(T a) {
  static_assert(std::is_baseOf<A,T>(), "only subclasses, please");
}

编辑,解释: 将 enable_if_t 视为满足条件时成为类型的东西(默认为 void )。

应用这一点,你的函数读作:
// true case:
template <typename T = void>
void templateFunction(T a) {}

// false case:
template <typename T = nonsense>
void templateFunction(T a) {}

您的调用仍然与 false 情况下的模板匹配!

现在,将此应用于我建议的代码:
//true case:
template <typename T>
void templateFunction(T a) {}

//false case:
template <typename T>
*nonsense* templateFunction(T a) {}

在这里,该函数在 false 情况下根本不存在,因此会产生编译错误。

关于templates - 如何使用 std::enable_if_t 和 std::is_base_of 来检查 SFINAE 的编译时继承?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45047497/

相关文章:

c++ - 当我们有一个模板类有模板指针时,如何使用继承

c++ - 如何在 C++ 中不使用 cin 扫描字符串?

c++ - 如何根据模板参数是否具有别名来专门化类型

c++ - C++方法从另一个模板类和 namespace 泄漏

c++ - 是否可以将模板专门用于语言链接?

c++ - 如何在编译时检测平凡的析构函数?

c++ - 返回模板的嵌套类时出现语法错误

ajax - 加载部分模板 Ajax - 使用 Grails

c++ - 调用函数中没有在被调用函数主体之前特别排序的这些评估是什么?

c++ - 模板构造函数一个参数 const 而不是 const