如何使用 std::enable_if 元函数实现 class 模板函数?

How can I implement a class template function with a std::enable_if metafunction?

我在我的 class 模板中使用了 std::enable_if 元函数来指定它只允许为以 GameCard 作为基础的变量生成 classes class。当我内联实现函数时,它本身就可以正常工作。但是,如果我想在 header body 之外实现模板函数,我会 运行 陷入无法弄清楚如何正确指定我想要实现的函数的问题。

删减示例代码:

#include <string>
#include <memory>
#include <vector>

struct GameCard {};

template<class T, class = std::enable_if_t<std::is_base_of<GameCard, T>::value>>
struct CardStack {
  std::vector<T> cards;
  bool Test();
};

我的 IDE 生成这个作为函数规范:

template<class T, class>
bool CardStack<T, <unnamed>>::Test() {
  return false;
}

这显然是错误的,因为我遇到了编译器错误。但是我不知道如何正确地做。你们有人知道怎么做吗?

函数成员定义应该是这样的:

template <class T, class U>
bool CardStack<T, U>::Test() {
    // body of function
}

Live example


解释很简单,这里没有反魔法。 只需遵循 C++.

的正常句法规则

你的 class 的定义是一个模板 class 有两个模板参数:

template<class, class>
struct CardStack { /* ... */ };

T是第一个的名字。 另一方面,第二个没有任何类型名称,只有默认类型 (= ...)。 默认类型(类似于函数的默认参数)不必在定义中指定。

因此,每个方法的定义应采用以下形式:

template <class T, class U>
bool CardStack<T, U>::MethodName() {}

class 的定义应该是:

template<class T, class Enabler>
bool CardStack<T, Enabler>::Test() {
  return false;
}

但是目前,您 class 可能被劫持了:

CardStack<int>CardStack<int, void> 由于 SFINAE 而无法编译,

CardStack<int, char> 将是 "valid"(由于 intCardStack 实现中产生的硬错误而导致无法编译的风险).

static_assert 在你的情况下似乎足够了:

template<class T>
struct CardStack {
  static_assert(std::is_base_of<GameCard, T>::value);

  std::vector<T> cards;
  bool Test();
};

class 定义更简单:

template<class T>
bool CardStack<T>::Test() {
  return false;
}