const-of-const和指向const的指针的重载函数

Fab*_*orr 10 c++ arrays templates pointers overloading

我可以使用模板函数捕获数组及其(编译时)大小,如下所示:

template<int N>
void foo(const int (&)[N]) {
    std::cout << "foo(const int (&)[N])\n";
}
Run Code Online (Sandbox Code Playgroud)

但是,我想重载foo以允许指向const的指针,以便在数组类型上调用函数时使用第一个重载,而在直接调用指针时调用第二个重载.

void foo(const int *) {
    std::cout << "foo(const int *)\n";
}

int main() {
    int a[1] = { 0 };
    foo(a);
    const int b[1] = { 0 };
    foo(b);
}
Run Code Online (Sandbox Code Playgroud)

Try it on ideone

这里,第一个重载被调用a,第二个过载被调用b.

我的猜测是,a编译器必须执行转换为const,这意味着它foo(const int *)不是一个完美的匹配,但我已经迷失了为什么这甚至不是一个模糊的函数调用.

如何更改代码,以便在两种情况下都调用第一个重载?

101*_*010 3

为什么它不起作用

在您的示例中,编译器匹配会考虑这两个重载。这里出现了重载解决方案来救援,以消除一个并保持最佳匹配。根据标准草案N4527 13.3.3/1.6 最佳可行功能 [over.match.best]:

F1 不是函数模板特化,F2 是函数模板特化

在我们的例子中,F1 是void foo(const int *)F2template<int N> void foo(const int (&)[N])。因此,F1 将优于 F2,因为 F1 不是模板特化,而 F2 是。

解决方案

在第二个重载中通过引用传递指针:

void foo(const int *&) {
    std::cout << "foo(const int *)\n";
}
Run Code Online (Sandbox Code Playgroud)

现场演示

为什么建议的解决方案有效

现在,正如 dyp 在评论中已经提到的那样,如果您通过引用传递指针(如上面所示),则此匹配将被破坏,因为无法与 toconst int *&匹配。int*int[N]

  • 您能解释一下为什么这种方法有效但原始方法无效? (2认同)
  • @trion 在传递 `const int[N]` 时,OP 中的两个函数都被视为重载决策的精确匹配。第二个重载不是模板,因此它是首选。在这个答案中,“const int *&amp;”不能绑定到“int*”或“int[N]”参数,因为否则可能会为其分配一个“const int*”并违反 const 正确性(想象一下之后的调用者改变指向的对象)。 (2认同)