Почему использование параметра шаблона по умолчанию для функции, также используемой в параметре лямбда, не работает - PullRequest
1 голос
/ 14 июля 2020

Возьмите следующий фрагмент кода C ++, который отлично компилируется (g cc 10.1.0): -

#include <iostream>
#include <string>
#include <functional>

template <class T = std::string>
void foo(T src, std::function<void(T&& t)> completionFn)
{
    completionFn(std::move(src));
}

int main(int argc, char *argv[])
{
    foo<std::string>("hello", [] (auto && t) {
        std::cout << t << std::endl;
    });

    return 0;
}

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

int main(int argc, char *argv[])
{
    foo<>("hello", [] (auto && t) {
        std::cout << t << std::endl;
    });

    return 0;
}

Мне, вероятно, не хватает чего-то очевидного.

Вот результат компилятора : -

src/scanner_test.cpp: In function ‘int main(int, char**)’:
src/scanner_test.cpp:19:6: error: no matching function for call to ‘foo(const char [6], main(int, char**)::<lambda(auto:11&&)>)’
   19 |     });
      |      ^
src/scanner_test.cpp:10:6: note: candidate: ‘template<class T> void foo(T, std::function<void(T&&)>)’
   10 | void foo(T src, std::function<void(T&& t)> completionFn)
      |      ^~~
src/scanner_test.cpp:10:6: note:   template argument deduction/substitution failed:
src/scanner_test.cpp:19:6: note:   ‘main(int, char**)::<lambda(auto:11&&)>’ is not derived from ‘std::function<void(T&&)>’
   19 |     });

Что мне не хватает? Спасибо! Прошу прощения, если это глупый вопрос.

1 Ответ

3 голосов
/ 14 июля 2020

Параметр шаблона по умолчанию используется только в том случае, если шаблон НЕЛЬЗЯ определить из контекста. В заданном контексте foo<>("hello", ...) шаблон T определяется как const char [6] (как указано в сообщении об ошибке). Для функций это всегда будет иметь место для параметров шаблона, которые относятся к реальным параметрам функции.

Решение, которое вы, возможно, ищете:

#include <iostream>
#include <string>
#include <functional>

template <class T>
void foo(T src, std::function<void(std::string&& t)> completionFn)
{
    //NOTE cast here to std::string, ensures we always have an std::string
    completionFn(std::move((std::string&)src));
}

int main(int argc, char *argv[])
{
    foo("hello", [] (std::string&& t) {
        std::cout << t << std::endl;
    });

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