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

发布于 2024-09-15 10:47:38 字数 1311 浏览 1 评论 0原文

我有两个函数:

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 的行为符合预期,而使用文字“liter.”调用 foo : Hello World”则不然,尽管两者具有相同的类型(根据 RTTI)。

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

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

谢谢 !

编辑

请注意,获得所需结果(即让文字字符串与 foo(const char (& p)[T_Size]) 函数匹配的方法)是删除 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 更好地匹配字符串文字,并且仍然允许用户使用指针(在优化编译模式中将删除间接寻址)。

我在 g++ 4.4.3 上测试了它,但我相信它在每个编译器上都会以相同的方式工作。

I have two functions :

void foo(const char * p)

and

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

Given the call:

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

Apparently, calling foo with a stack-based correctly declared array behaves as expected, while calling foo with a literal "liter. : Hello World" does not, despite the two having the same type (according to RTTI).

What are exactly the rules followed by the symbol lookup to choose one overload over the other ?

Why the different behaviour between a declared array and a string literal ?

Thanks !

Edit

Note that a way to have the desired result (i.e. have a litteral string match the foo(const char (& p)[T_Size]) function) is to remove the void foo(const char *p) and add instead:

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

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

This indirection makes the templated foo a better match for string litterals, and still enables the user to use pointers (the indirection will be removed in optimized compilation mode).

I tested it on my g++ 4.4.3, but I believe it will work the same way on every compiler.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

↘人皮目录ツ 2024-09-22 10:47:38

标准第 13 章(重载解决方案)中的表 9 将“数组到指针”转换(对于非模板)与“不需要转换”(对于模板版本)具有相同的等级(精确匹配)。

在其他条件相同的情况下,非模板版本优于模板版本。

Table 9 in Chapter 13(Overload Resolution) of the Standards, ranks "Array to pointer" conversion (for non-template) to be of the same rank (EXACT MATCH) as "no Conversion Required" (for the template version).

Everything else being the same, the non-template version is preferred over the template version.

罗罗贝儿 2024-09-22 10:47:38

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

The compiler will always call non-templated overloads if available in comparison to templated functions. You provided a perfectly adequate non-templated overload, so the compiler calls it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文