【问题标题】:Overload function for both arrays-of-const and pointers-to-const常量数组和常量指针的重载函数
【发布时间】:2015-10-06 07:25:23
【问题描述】:

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

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

但是,我想重载 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);
}

Try it on ideone

这里,a 调用了第一个重载,b 调用了第二个。

我的猜测是,对于a,编译器必须执行转换为常量,这意味着foo(const int *) 不是完美匹配,但我不知道为什么这甚至不是一个模棱两可的函数调用。

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

【问题讨论】:

  • std::array 不会发生这种情况:p

标签: c++ arrays templates pointers overloading


【解决方案1】:

为什么它不起作用

在您的示例中,编译器匹配都考虑了两个重载。这里有超载解决方案来拯救,以消除一个并保持最佳匹配。根据草案标准N452713.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";
}

LIVE DEMO

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

现在,正如 cmets 中已经提到的 dyp,如果您如前所述通过引用传递指针,则此匹配将被破坏,因为 const int *&amp; 无法匹配到 int* 也无法匹配到 int[N]

【讨论】:

  • 你能解释一下为什么这行得通,但原来的方法不行吗?
  • 此重载不适用于非 const 指针。 demo
  • @rozina 我知道,对于非 const 指针,可能会有另一个重载 void foo(int *&amp;)
  • 似乎不是一个有用的重载。也不适用于 Alexander 的示例。
  • @trion 在传递const int[N] 时,OP 中的两个函数都被视为重载解析的精确匹配。第二个重载不是模板,因此它是首选。在这个答案中,const int *&amp; 不能绑定到 int*int[N] 参数,因为否则可能会为它分配 const int* 并违反 const 正确性(想象调用者之后会改变指向的对象)。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-23
  • 1970-01-01
  • 2021-04-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多