Enable_if как параметр шаблона - PullRequest
2 голосов
/ 24 апреля 2019

Скажите, пожалуйста, почему этот ответ работает.

  1. Что случилось с enable_if таким, что мы можем опустить его после этого? (дальнейшее использование структуры Foo не требует этого enable_if в параметрах шаблона)
  2. Разве этот код не должен выглядеть примерно так:

Исходная версия:

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

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

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

Отредактированная версия:

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

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

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

1 Ответ

3 голосов
/ 24 апреля 2019

Это случилось:

  1. Автор опубликовал рабочий код (<Policy> присутствовал);

  2. В комментариях было некоторое обсуждение, которое привело автора к редактированию кода, и он допустил ошибку (<Policy> был удален);

  3. Я исправил ошибку, вернув недостающий <Policy>.


Может кто-нибудь объяснить, почему работает даже отредактированная версия?

Когда вы пытаетесь создать экземпляр Foo<T>, объявление с параметрами шаблона по умолчанию учитывается компилятором. Параметр по умолчанию оценивается, и если std::is_base_of<BasePolicy, Policy>::value равно false, то enable_if выдает ошибку, удобную для SFINAE.

Если std::is_base_of<BasePolicy, Policy>::value равно true, выбирается частичная специализация.

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

// is equivalent to

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

Вышеуказанные специализации эквивалентны, потому что typename std::enable_if<true>::type по умолчанию void.

...