SFINAE: удалить функцию с тем же прототипом - PullRequest
0 голосов
/ 21 мая 2018

Интересно, в чем разница между этим кодом, который работает:

#include <type_traits>
#include <iostream>

template<typename T> using is_ref = std::enable_if_t<std::is_reference_v<T>, bool>;
template<typename T> using is_not_ref = std::enable_if_t<!std::is_reference_v<T>, bool>;

template<typename T, is_ref<T> = true>
void foo(T&&) {
    std::cout << "ref" << std::endl;
}

template<typename T, is_not_ref<T> = true>
void foo(T&&) {
    std::cout << "not ref" << std::endl;
}

int main() {
    int a = 0;
    foo(a);
    foo(5);
}

и тем, который не работает:

#include <type_traits>
#include <iostream>

template<typename T> using is_ref = std::enable_if_t<std::is_reference_v<T>, bool>;
template<typename T> using is_not_ref = std::enable_if_t<!std::is_reference_v<T>, bool>;

template<typename T, typename = is_ref<T>>
void foo(T&&) {
    std::cout << "ref" << std::endl;
}

template<typename T, typename = is_not_ref<T>>
void foo(T&&) {
    std::cout << "not ref" << std::endl;
}

int main() {
    int a = 0;
    foo(a);
    foo(5);
}

В чем истинная разница между typename = is_ref<T>и is_ref<T> = true?

1 Ответ

0 голосов
/ 21 мая 2018

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

void foo(int i = 4);
void foo(int i = 5);

И также это плохо сформировано:

template <typename T=int> void foo();
template <typename T=double> void foo();

Имея это в виду, ваш первый случай:

template<typename T, is_ref<T>>
void foo(T&&);

template<typename T, is_not_ref<T>>
void foo(T&&);

Два объявления здесь уникальны, потому что второй параметр шаблона отличается между двумя объявлениями.Первый имеет параметр шаблона нетипичного типа, тип которого std::enable_if_t<std::is_reference_v<T>, bool>, а второй имеет параметр шаблона нетипичного типа, тип которого std::enable_if_t<!std::is_reference_v<T>, bool>.Это разные типы.

Принимая во внимание, что ваш второй случай:

template<typename T, typename>
void foo(T&&);

template<typename T, typename>
void foo(T&&)

Это явно одна и та же подпись - но мы только что ее дублировали.Это плохо сформировано.

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