我想要一个函数重载,其中一个用例通过指针传递非数组参数,另一个用例通过引用传递 C 数组参数。
不幸的是,传递 C 数组参数会选择两个候选函数,因为 C 数组的指针衰减必须处于相同的考虑级别,从而使情况变得模棱两可。
#include <iostream>
static void foo(int* p) {
std::cout << "int* -> " << *p << "\n";
}
static void foo(int (&a)[4]) {
std::cout << "int[4] -> "
<< a[0] << " "
<< a[1] << " "
<< a[2] << " "
<< a[3] << "\n";
}
int main() {
int array[4]{ 10, 20, 30, 40 };
foo(array); // error: call to 'foo' is ambiguous
foo(array + 3);
}
我目前正在使用此解决方法。我对此解决方法不满意。
static void foo(int (*a)[4]) { /*...*/ }
...这将通过以下方式调用...
foo(&array);
将传递指针改为传递引用到指针的替代方法void foo(int*& p)
将会阻止调用它,foo(array + 3)
因为那是一个右值。
是否有另一种方法(或模板魔法)可以消除这两种情况的歧义?
上下文最好是 C++17,但如果可以用 C++20 或更高版本来表达一个不错的解决方案,那仍然会引起人们的兴趣。
(XY 问题?)原始上下文是将指针或数组作为类构造函数参数传递。原始上下文是尝试制作一个“胖指针”,就像 Google 的 Miracle Pointer 一样,它是常规原始指针的指针替代品,但包含跨度和偏移信息以及偏执检查(这确实会产生额外的运行时开销)。我试图将示例简化为突出且最小的再现案例。
更新(回复评论):最终,我希望它也支持并区分 aconst int[4]
和 a const int*
。
调度员在
if constexpr (std::is_array
工作。或相同:
因此,您应该人为地使非数组构造函数变得更糟。最简单的方法已在@user17732522 的评论中提供。但如果出于某种原因该方法对您不起作用,这里有一个较旧的方法:引入用户定义的转换。
实例: https: //godbolt.org/z/1o9KT833x