T = char не может быть выведено для std:: basic_string <T> foo = "foo"?
Вопрос:
В приведенном ниже коде вывод типа аргумента шаблона кажется неудачным для первого образца, но не для второго образца. Я не понимаю, почему первый образец не выводит T = char
. Я бы подумал, что T
может быть выведен при преобразовании из "foo"
в std::bacis_string<T>
, но даже если это не сработало, я предоставляю второй аргумент функции, который, я думаю, явно сдерживал бы T
до char
. Почему это не удается?
Не работает:
#include <iostream>
#include <string>
template <typename T>
void print(const std::basic_string<T>& a, const std::basic_string<T>& b)
{
std::cout << a << b << std::endl;
}
int main()
{
std::string bar = "bar";
print("foo", bar);
}
Ошибка:
string.cpp:14:5: error: no matching function for call to 'print'
print("foo", bar);
^~~~~
string.cpp:6:6: note: candidate template ignored: could not match
'basic_string<type-parameter-0-0, char_traits<type-parameter-0-0>,
allocator<type-parameter-0-0> >' against 'char const[4]'
void print(const std::basic_string<T>& a, const std::basic_string<T>& b)
^
1 error generated.
Работы:
#include <iostream>
#include <string>
template <typename T>
void print(const std::basic_string<T>& a, const std::basic_string<T>& b)
{
std::cout << a << b << std::endl;
}
int main()
{
std::string foo = "foo";
std::string bar = "bar";
print(foo, bar);
}
Ответы
Ответ 1
Проблема в том, что здесь требуется преобразование. Чтобы вывести T
, компилятор должен был бы проверить все возможные экземпляры std::basic_string
и посмотреть, какие из них можно построить из const char*
(или фактически const char (&)[4]
). Это, конечно, невозможно, так как их бесконечно много. Причина, по которой он должен проверять все и не может просто проверять определение первичного шаблона для конструкторов, принимающих const char*
или const char(&)[4]
, - это то, что для некоторых T
, std::basic_string<T>
может быть частично или полностью специализированным, а члены этих специализаций не имеют отношения к членам первичного шаблона.
Ответ 2
Вот короткая версия ответа.
У компилятора есть char const[]
и он хочет преобразовать его в std::basic_string<T>
. Как это работает, что T
? Вы знаете, что хотите сопоставить T = char
, но компилятор этого не знает.
Он мог бы искать конструктор basic_string<T>(char const *)
, например. Даже если это существует, он все еще не говорит, что должно быть T
.
Компилятор не перебирает все возможные имена, о которых он знает, и пытается выполнить basic_string<T>
для каждого из них, а затем посмотреть, есть ли соответствующий конструктор.
Аналогичный пример:
template<typename T>
struct Foo
{
Foo(T t) {}
};
int main()
{
Foo(0); // error, can't deduce Foo<int>
}