Подстановка шаблонной функции работает, только если в одном параметре не используется std :: function - PullRequest
0 голосов
/ 08 сентября 2018

У меня есть функция шаблона с двумя параметрами шаблона. Первый (T) выводится на основе типа первого параметра, переданного функции. Вторая (ItrT) выводится с использованием std::type_traits и T. Когда я использую ItrT в качестве типа для параметра (см. Функцию bar), то все типы выводятся неявно, но когда я использую std::function<void(ItrT)> в качестве типа параметра (см. Функцию foo), чем правильные типы выводится только при полном указании всех параметров шаблона (даже если используется тот же код, что и в определении функции). Можно было бы предположить, что использование ItrT внутри шаблона не изменит способность компиляторов выводить шаблон. Почему это не так? и что мне нужно сделать, чтобы все параметры шаблона могли быть выведены неявно ?. Я использую C ++ 17.

template <class T, class ItrT = typename std::iterator_traits<T>::value_type>
auto foo(T iterator, std::function<void(ItrT)> expr) -> void{
}

template <class T, class ItrT = typename std::iterator_traits<T>::value_type>
auto bar(T iterator, ItrT expr) -> void{
}

int main() {
    std::vector<int> vec = {1, 2, 3};

    bar(vec.begin(), 1); // Compiles!

    foo(vec.begin(), [](int) {}); // Failes!

    foo<decltype(vec.begin()),
        std::iterator_traits<decltype(vec.begin())>::value_type>
        (vec.begin(), [](int) {}); // Compiles!
}

Спасибо заранее.

1 Ответ

0 голосов
/ 08 сентября 2018

Я предполагаю, что путаница здесь связана с ролью аргументов шаблона по умолчанию.

Правило не так: попробуйте вывести параметр. Если вычет не удался, используйте значение по умолчанию (если оно предусмотрено).

Скорее, правило таково: если параметр находится в выведенном контексте, выведите его. Если вычет не удается, прервать. Если это не в выведенном контексте, и это не предоставлено явно, используйте аргумент по умолчанию. Другими словами, аргумент по умолчанию используется, только если параметр не находится ни в выведенном контексте, ни в явном виде.

В обоих ваших примерах ItrT находится в выведенном контексте, поэтому аргумент шаблона по умолчанию вообще не рассматривается. Разница между ними заключается в том, что вы можете выводить T из лямбды (вы просто соответствуете ее типу), но вы не можете выводить function<void(T) из лямбды - лямбда может быть преобразовал в соответствующий function, но лямбда не a function. Шаблон вычета не делает преобразования. Вычисление шаблона просто соответствует шаблонам.

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