Как реализовать функцию шаблона класса с метафункцией std :: enable_if? - PullRequest
0 голосов
/ 14 февраля 2020

Я использовал метафункцию std::enable_if в своем шаблоне класса, чтобы указать, что ему разрешено генерировать классы только для переменных, которые имеют GameCard в качестве базового класса. Это прекрасно работает само по себе, когда я реализую встроенные функции. Однако, если я хочу реализовать функции шаблона вне тела заголовка, я сталкиваюсь с проблемой, которую не могу понять, как правильно указать функцию, которую я хочу реализовать.

Сократить пример кода:

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

Это, очевидно, неправильно, так как я получаю ошибки компилятора. Но я понятия не имею, как это сделать правильно. Кто-нибудь из вас знает, как сделать это правильно?

Ответы [ 2 ]

3 голосов
/ 14 февраля 2020

Определение вне класса должно быть:

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

Но в настоящее время ваш класс может быть угнан:

Принимая во внимание, что CardStack<int> или CardStack<int, void> не будут компилироваться благодаря SFINAE,

CardStack<int, char> будет «допустимым» (риск не скомпилироваться из-за серьезной ошибки, вызванной int в реализации CardStack).

static_assert кажется достаточно в вашем случае:

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

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

с более простым определением вне класса:

template<class T>
bool CardStack<T>::Test() {
  return false;
}
2 голосов
/ 14 февраля 2020

Определение элемента функции должно выглядеть примерно так:

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

Пример в реальном времени


Объяснение довольно простое, спины волхвов нет c здесь. Просто следуйте обычным синтаксическим c правилам C ++ .

Определение вашего класса - это шаблонный класс с двумя параметрами шаблона:

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

T это имя первого. С другой стороны, второй не имеет никакого имени типа, а только тип по умолчанию (= ...). Тип по умолчанию (аналогично аргументам по умолчанию для функций) не обязательно указывать в определении.

Поэтому каждое определение метода должно иметь вид:

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