Определение методов класса шаблона с enable_if в качестве параметра шаблона - PullRequest
10 голосов
/ 12 марта 2012

Я задавал этот вопрос ранее, где было представлено решение . Решение великолепно в том, что касается вопроса, но теперь я запутался в том, как определить методы вне класса, т. Е. Я хотел бы определить методы в файле .inl. Какой будет синтаксис в этом случае?

Просто чтобы прояснить, для класса шаблона определение метода будет:

template <typename T>
struct Foo
{
  Foo();
};

// C-tor definition
template <typename T>
Foo<T>::Foo()
{
}

Как бы я определил методы для класса шаблона с enable_if в качестве одного из параметров?

template <typename Policy, enable_if< is_base<BasePolicy, Policy>::value >::type >
struct Foo
{
  Foo();
};

// C-tor definition -- ???

Ответы [ 2 ]

14 голосов
/ 12 марта 2012

Судя по всему, вы хотите сделать что-то вроде этого:

template <typename Policy,
          typename = typename std::enable_if<std::is_base_of<BasePolicy, Policy>::value>::type >
struct Foo;

template <typename Policy>
struct Foo<Policy> {
    Foo();
};

template <typename Policy>
Foo<Policy>::Foo() {
}

Это скрытно использует аргумент по умолчанию в нескольких местах: не запутайтесь, в нескольких местах скрыт void.

8 голосов
/ 12 марта 2012

Вот как на самом деле может работать SFINAE с частичной специализацией:

template<typename T, typename Sfinae = void>
struct Foo {
    /* catch-all primary template */
    /* or e.g. leave undefined if you don't need it */
};

template<typename T>
struct Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type> {
    /* matches types derived from BasePolicy */
    Foo();
};

Определение этого конструктора может быть неловко введено с помощью:

template<typename T>
Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type>::Foo()
{
    /* Phew, we're there */
}

Если ваш компилятор поддерживает псевдонимы шаблона (это особенность C ++ 11), в которой вы можете сократить многословность:

template<typename T>
using EnableIfPolicy = typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type;

// Somewhat nicer:

template<typename T>
struct Foo<T, EnableIfPolicy<T>> {
    Foo();
};

template<typename T>
Foo<T, EnableIfPolicy<T>>::Foo() {}

Примечание: ваш исходный ответ относится к утилитам Boost, таким как boost::enable_if_c и boost::is_base_of.Если вы используете это вместо std::enable_if и std::is_base_of (которые из C ++ 11), тогда использование выглядит как

typename boost::enable_if<boost::is_case_of<BasePolicy, T> >::type

, что дает преимущество в избавлении от одного ::value.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...