basic_string <CharT>与CharT*

aki*_*kim 3 c++ templates stdstring c++11 type-deduction

这是一个FAQ,但我找不到令人满意的答案.在我的项目中,我们支持std::string并且现在还必须支持宽字符串.所以我们想要转移basic_string,但是,事情就会停止运行,并且需要明确地拼写参数:

#include <string>

template <typename CharT, typename Traits, typename Allocator>
void
foo(const std::basic_string<CharT, Traits, Allocator>&)
{}

template void foo(const std::string&);

// template void
// foo<char, std::char_traits<char>, std::allocator<char>>(const std::string&);

void bar(const std::string& s)
{}

int main()
{
  bar("abc");
  foo<char, std::char_traits<char>, std::allocator<char>>("def");
  foo("def");
}
Run Code Online (Sandbox Code Playgroud)

好吧,由于众所周知的原因,它失败了:

clang++-mp-3.5 -Wall -std=c++11 foo.cc 
foo.cc:20:3: error: no matching function for call to 'foo'
  foo("def");
  ^~~
foo.cc:5:1: note: candidate template ignored: could not match
      'basic_string<type-parameter-0-0, type-parameter-0-1, type-parameter-0-2>'
      against 'char const[4]'
foo(const std::basic_string<CharT, Traits, Allocator>&)
^
Run Code Online (Sandbox Code Playgroud)

我不明白它为什么适用bar?为什么foofor 的显式实例化char(无论是使用显式模板参数还是使用演绎)都足以解决这个问题?

看来,这意味着,而不是使用模板和basic_string公开的API中,我们将使用它作为一个实现细节,但重载暴露用户std::string,std::wstring等等.这是一种耻辱.

谢谢!

0x4*_*2D2 5

对于bar("abc")有一个从隐式转换char const[4]std::string.foo不同之处bar在于它实际上不是函数而是函数模板.需要知道其模板参数才能构建正确的函数.

第一次调用foo显式提供了模板参数,因此它构建了一个如下所示的函数:

void foo(const std::basic_string<char, std::char_traits<char>, std::allocator<char>>&);
Run Code Online (Sandbox Code Playgroud)

隐式转换开始了,一切都很好.

第三个电话不提供模板参数,所以编译器必须弄清楚的类型CharT,TraitsAllocator从类型char const[4].此类型不携带该信息,因此扣除失败,重载解析无法找到正确的功能.