类型推导/替换失败

Type deduction/substitution failure

本文关键字:替换 失败 类型      更新时间:2023-10-16

考虑以下示例。

#include <string>

template<class CharT, class Traits = std::char_traits<CharT >, class Allocator = std::allocator<CharT >>
void f(const std::basic_string<CharT, Traits, Allocator>& s) {
}
int main() {
f("Hello World!");
}

编译时,我得到

不匹配的类型‘const std::basic_string<_CharT, _Traits, _Alloc>’ and ‘const char []’

为什么编译器不能扣除"CharT"并转换为适当的basic_string<>?我希望只有一个f()的签名对任何存在到basic_string<>转换的参数类型有效,有解决这个问题的方法吗?

您正在向函数传递一个原始字符串,它不是std::string,而是一个字符数组,一个const char []
即使std::string有一个获取char数组的构造函数,在模板论证推导过程中也不会应用隐式类型转换(这正是您遇到的问题)。有关该主题的更多信息,请参阅此线程。

有两种可能的解决方案:

  1. std::string而不是原始字符串传递给函数:

    f( std::string( "hello" ) );
    
  2. 编写一个使用原始字符串的函数重载:

    template<typename CHAR_T , std::size_t LENGHT>
    void f( const CHAR_T (&string)[LENGTH] )
    {
    f( std::string( string ) ); //Just wrap the call to not duplicate code.
    }
    

您所要求的是编译器对每个basic_string<T>进行迭代,直到确定正好有一个T匹配为止。或者,它可以颠倒可能的图灵完整过程,找出template参数是什么。template参数的推导就是模式匹配:它获取参数,并将其与您的模式匹配,然后简单地推导类型。如果您想要更多,您需要告诉它如何反转从CharTbasic_string<CharT,A>构造函数的映射。C++1y使概念更简单,但你想要的那种机器仍然不存在。

到目前为止,最简单的解决方案是为charwchar_tbasic_strings(实际函数,而不是templates)设置两个重载,然后让它们调用一个template泛型函数,就像您在CharT中明确传递的那样。

Fancier将涉及实际执行上述反转的代码,其中您可能让它从一组可接受的字符串中工作,并检查可以从哪些参数中构造参数,断言只有一个选项,并以这种方式推导CharT。虽然有趣,但我怀疑这是否值得。

这样就可以了。

您正在为您的函数指定一个char数组,witch应该得到std::string。您需要使用构造函数来转换这些。

#include <string>

template<class CharT, class Traits = std::char_traits<CharT >, class Allocator = std::allocator<CharT >>
void f(const std::basic_string<CharT, Traits, Allocator>& s) {
}
int main() {
std::string str("Hello World!");
f(str);
}