【问题标题】:std::basic_string as a parameter of a function template cannot be deduced from const char*std::basic_string 作为函数模板的参数不能从 const char* 推导出来
【发布时间】:2020-08-10 02:27:37
【问题描述】:

为什么将std::basic_string作为函数模板的参数,从const char*推导失败,而直接构造却可以推导成功?

#include <string>
#include <iostream>
template<class Char/*, class Traits, class Allocator*/>   
                      //^doesn't matter whether the second and third template parameter is specified
void printString(std::basic_string<Char/*, Traits, Allocator*/> s)
{
    std::cout << s;
}
int main()
{
    printString("hello");    //nope
    std::basic_string s{ "hello" };//works
}

我找到了一个相关的帖子here,但答案并没有解释背后的原因

【问题讨论】:

  • 如果多个特化具有匹配的构造函数,编译器将无法选择一个类型。

标签: c++ templates implicit-conversion template-argument-deduction


【解决方案1】:

因为template argument deduction中没有考虑隐式转换(从const char*std::basic_string&lt;char&gt;),导致推导出模板参数Char失败。

类型推导不考虑隐式转换(除了上面列出的类型调整):这是overload resolution 的工作,稍后会发生。

您可以显式指定模板参数,

printString<char>("hello");

或显式传递std::basic_string

printString(std::basic_string("hello"));

【讨论】:

  • 什么算作“隐式转换”?如果它是一个只能用一个参数调用的构造函数,我仍然会收到错误,例如将std::pair&lt;T1, T2&gt; 作为参数,并用printPair({1,2}) 调用。但它需要 2 个参数来构造。
  • @szppeter 指的是const char*std::basic_string&lt;char&gt;的转换。抱歉,我无法理解您对 std::pair 的意思。你能提供它的代码sn-p吗?
  • 例如。 template&lt;typename T1, typename T2&gt; void printPair(std::pair&lt;T1, T2&gt;p) { std::cout&lt;&lt;p.first&lt;&lt;p.second;} int main(){ printPair({1,2}); }
  • @szppeter 这里有同样的问题。支撑初始化列表{1,2} 可以转换为(构造)std::pair,但在模板推导中不考虑。如果指定printPair&lt;int, int&gt;({1,2});之类的模板参数绕过推导,那么{1,2}转换为std::pair再传给printPair,一切正常。
  • @szppeter,它们可以被推断出来,只是当你传入不同的类型时就不行了。您的配对仍然存在相同的基本问题:如果多个特化具有匹配的构造函数,编译器会推断出 T1T2 是什么? (例如,完全有可能出现像 pair&lt;Foo, Foo&gt;pair&lt;Bar, Bar&gt; 这样的后续特化,它们都有一个采用 std::initializer_list&lt;int&gt; 的构造函数。)一般来说这是不可能的,而且 C++ 并不知道某些东西是如何工作的时间,然后在代码超出这些特定情况时出错。
猜你喜欢
  • 2012-02-21
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多