const char *和const char(& p)[T_Size]之间的最佳查找匹配

时间:2010-08-19 12:57:32

标签: c++ templates argument-dependent-lookup

我有两个功能:

void foo(const char * p)

template<size_t T_Size>
void foo(const char (& p)[T_Size]) ;

接到电话:

int main(int argc, char* argv[])
{
   char a[21] ;                          // typeid : A21_c
   sprintf(a, "a[21] : Hello World") ;

   const char * b = "b : Hello World" ;  // typeid : PKc

   // note that literal "liter. : Hello World" has a typeid : A21_c

   foo(a) ;                      // calls foo(const char (& p)[T_Size])
   foo(b) ;                      // calls foo(const char * p)
   foo("liter. : Hello World") ; // calls foo(const char * p) ???

   return 0 ;
}

显然,使用基于堆栈的正确声明的数组调用foo的行为符合预期,而使用文字“升。:Hello World”调用foo则不会,尽管两者具有相同的类型(根据RTTI)。

符号查找遵循的规则是什么,以选择一个重载而不是另一个?

为什么声明的数组和字符串文字之间的行为不同?

谢谢!

修改

请注意,获得所需结果的方法(即使用与foo(const char (& p)[T_Size])函数匹配的litteral字符串)是删除void foo(const char *p)并添加:

struct FooIndirect
{
    const char * m_p ;
    FooIndirect(const char *p) : m_p(p) {}
} ;

void foo(const FooIndirect & p)
{
    // do something with p.m_p
}

这种间接使得模板化的foo更好地匹配字符串litterals,并且仍然允许用户使用指针(在优化的编译模式中将删除间接)。

我在g ++ 4.4.3上测试过它,但我相信它在每个编译器上的工作方式都是一样的。

2 个答案:

答案 0 :(得分:4)

标准的第13章(过载分辨率)中的表9,将“数组到指针”转换(对于非模板)排名为“无需转换”(对于模板版本)具有相同等级(精确匹配) )。

其他所有内容都相同,非模板版本优先于模板版本。

答案 1 :(得分:1)

与模板化函数相比,编译器将始终调用非模板化重载(如果可用)。您提供了一个非常适合的非模板化重载,因此编译器会调用它。