T = char 不能推断出 std::basic_string<T> foo = "foo" ?

T = char can't be deduced for std::basic_string<T> foo = "foo"?

本文关键字:foo lt gt 不能 char 推断出 std basic string      更新时间:2023-10-16

问题:在下面的代码中,第一个样本的模板参数类型推导似乎失败了,但第二个样本没有。我不明白为什么第一个样本不能推导出T = char。我认为当从"foo"转换为std::bacis_string<T>时,可以推导出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);
}

问题是这里需要转换。为了推导T,编译器必须检查std::basic_string的所有可能的实例化,并查看其中哪些可以从const char*(或实际上是const char (&)[4])构建。这当然是不可能的,因为它们有无限多。对于采用const char*const char(&)[4]的构造函数,它必须检查所有而不能只扫描主模板定义的原因是,对于某些Tstd::basic_string<T>可能是部分或完全专业化的,并且这些专业化的成员与主模板的成员没有关系。

以下是答案的简短版本。

编译器具有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>
}