类型扣除/替换失败

时间:2013-12-24 09:51:12

标签: c++

请考虑以下示例。

#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<>的任何参数类型都有效,是否有解决此问题的方法?

3 个答案:

答案 0 :(得分:6)

您正在将一个原始字符串传递给您的函数,该函数不是std::string,而是一个字符数组,const char []。 即使std::string有一个获取char数组的构造函数,在模板argumment推导期间也不会应用隐式类型转换(确切地说就是你遇到的问题)。有关该主题的更多信息,请参阅this thread

有两种可能的解决方案:

  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.
    }
    

答案 1 :(得分:1)

你问的是要求编译器迭代每个basic_string<T>,直到它确定只有一个T匹配。或者,它可以反转可能的图灵完成过程以找出template参数是什么。 template这样的参数推导就是模式匹配:它接受参数,并将其与模式匹配,并简单地推导出类型。如果您需要更多,您需要告诉它如何反映从CharTbasic_string<CharT,A>构造函数的映射。使用C ++ 1y可以轻松实现概念精简,但您想要的机器类型仍然不存在。

到目前为止,最简单的解决方案是对charwchar_t basic_string s(实际函数,而不是template s)进行两次重载,然后让它们调用template泛型函数,就像你在CharT明确传递的内容一样。

Fancier将涉及实际执行上述反转的代码,您可以从一组可接受的字符串中使用它,并检查可以构造哪些参数,断言只有一个选项,并推导{{1 }} 那样。虽然很有趣,但我怀疑这是值得的。

答案 2 :(得分:0)

这应该可以解决问题。

你正在为你的函数指定一个char数组,它应该得到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);
}