繁体   English   中英

区分接受与函数参数同名的常量和非常量参数的函数引用/指针

[英]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 ,它确实不包含任何函数模板。 因此,对func两个重载都尝试对fun参数推导,结果成功。 结果,参数fun变成了一个非推导的上下文,这意味着不能为Ret推导任何参数,并且调用失败,因为没有候选对象(正是 clang 抱怨的)。

要消除此调用的歧义,只需明确指定第一个模板参数的参数:

call<int>(mutableValue, func)

由于在一个模板参数推导中解决歧义似乎是不可能的:

如果您对调用站点的语法更改没有意见,您可以将调用分为两个调用/推导传递:

template<typename Arg>
auto call(Arg& val)
{
    return [&](auto (&fun)(Arg&)){ fun(val); };
}

被称为

call(mutableValue)(func)

然而,另一个缺点是 lambda 可能由调用者存储,并在捕获的引用不再有效时意外使用。

您可以将其隐藏在宏调用中,以便语法与您想要的匹配并减少误用的可能性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM