区分接受常量参数的函数引用/指针和与函数参数同名的非常量参数
Distinguish between function references/pointers accepting const and non-const argument with same name as function parameter
让我们考虑两个同名的函数:
int func(int&)
{
return 7;
}
int func(const int&)
{
return 5;
}
让我们在某处定义int mutableValue = 5
。call(mutableValue, func)
中的模板函数call
是否有可能只需要int func(int&)
? 我不想使用static_cast<int(&)(int&)>
- 因为它太吵了。
朴素实现:
template<typename Arg, typename Ret>
void call(Arg& val, Ret (&fun)(Arg&))
{
fun(val);
}
适用于 GCC,但不适用于 Clang - 解决方案必须适用于两个编译器。
只接受const Arg&
很容易。删除const Arg&
重载无济于事。
我相信clang是唯一能做到这一点的编译器。这不应该编译。只要要fun
的参数是不包含任何函数模板的重载集,就会尝试对重载集的每个成员进行模板参数推断。如果模板参数推导成功用于多个重载,则函数参数将成为非推导上下文 [temp.deduct.call]/6.2。
在所讨论的例子中,要fun
的参数是重载集func
,它确实不包含任何函数模板。因此,fun
的参数推导尝试用于func
的两个重载,结果成功。结果,参数fun
成为非推导上下文,这意味着无法推断出Ret
的参数,并且调用失败,因为没有候选项(这正是 clang 抱怨的(。
若要消除此调用的歧义,只需显式指定第一个模板参数的参数:
call<int>(mutableValue, func)
由于似乎不可能解决一个模板参数推导中的歧义:
如果您同意在呼叫站点更改语法,则可以将呼叫分为两个呼叫/扣除传递:
template<typename Arg>
auto call(Arg& val)
{
return [&](auto (&fun)(Arg&)){ fun(val); };
}
被称为
call(mutableValue)(func)
然而,另一个缺点是 lambda 可能由调用方存储,并在捕获的引用不再有效时意外使用。
您可以在宏调用中隐藏它,以便语法与您想要的语法匹配并减少误用的可能性。
相关文章:
- 如何创建长度由常量参数指定的数组
- 通过常量引用传递参数的矩阵模板类
- 具有常量引用参数的函数模板专用化
- 使用自动推导的 lambda 参数作为常量表达式
- C++:常量引用参数
- 常量参数"real"常量吗?
- 常量参数存储在哪里 (C++)?
- 常量函数,当其参数是对文字类型的引用时
- 区分接受常量参数的函数引用/指针和与函数参数同名的非常量参数
- 必须非常量别名参数及其默认参数常量
- 字符串参数常量字符* 和常量 wchar_t*
- 可选参数常量引用重新分配
- 推导模板化类参数的模板参数:常量问题
- 从函数参数常量字符串 (&) 设置值
- 为什么我必须声明这些引用参数常量或按值传递
- C++使用一个参数常量重载
- 如果要执行const_cast,为什么要制作参数常量?
- 模板非类型参数常量限制筛选器库
- 标记方法指针/引用参数常量真的会显著影响性能吗
- 当函数参数常量引用 T 时,为什么 T 的模板参数推导'skips'数组元素的恒定性?