字符串类型,参数匹配
#include <iostream>
#include <string>
void f(const std::string &) { std::cout << 1; }
void f(const void *) { std::cout << 2; }
int main() {
f("foo");
const char *bar = "bar";
f(bar);
}
答案是:22
字符串字面值不是std::string
类型,而是const char[]
类型。如果编译器要调用第一个函数声明的话,它会去找是否有用户定义的转换函数,然后创建一个临时的std::string
对象。然而它更倾向于调用f(const void *)
,因为是一个array-to-pointer conversion。
A string literal is not a std::string
, but a const char[]
. If the compiler was to choose f(const std::string&)
, it would have to go through a user defined conversion and create a temporary std::string
. Instead, it prefers f(const void*)
, which requires no user defined conversion.
好,问题来了,如果我再加几个定义呢?
template <class T>
void f(T &s) { std::cout << 3; }
template <int N>
void f(const char (&)[N]) { std::cout << 4; }
是不是感觉大脑要爆炸?
答案是:43,同样的,解析在下一期给出。
接上期,为什么f(42)
会出错呢?
因为参数为int
,模板实例化时会推断T
为int
,所以函数声明为void f(int&)
,而int
与int&
不匹配,所以会CE。
那有人会问了,那为什么字面值不能和const int &
匹配呢,字面值是可以绑定到const &
上的,然而,偏特化的函数版本void f(const int &)
中T
是const int
,而调用时T
推导为int
,不匹配。