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

Mam*_*ita 7 c++ templates metaprogramming

让我们考虑两个具有相同名称的函数:

int func(int&)
{
    return 7;
}
int func(const int&)
{
    return 5;
}
Run Code Online (Sandbox Code Playgroud)

让我们int mutableValue = 5在某处定义。是否有可能是模板函数callcall(mutableValue, func)将只需要int func(int&)?我不想使用static_cast<int(&)(int&)>- 因为它太吵了。

幼稚的实现:

template<typename Arg, typename Ret>
void call(Arg& val, Ret (&fun)(Arg&))
{
    fun(val);
}
Run Code Online (Sandbox Code Playgroud)

适用于 gcc,但不适用于 clang - 解决方案必须适用于两个编译器。

只接受const Arg&很容易。删除const Arg&过载无济于事。

Mic*_*zel 4

我相信 clang 是唯一能做到这一点的编译器。这不应该编译。只要 的参数fun是不包含任何函数模板的重载集,就会尝试对重载集的每个成员进行模板参数推导。如果模板参数推导对于这些重载中的多个重载都成功,则函数参数将成为非推导上下文[temp.deduct.call]/6.2

在相关示例中, 的参数fun是重载集func,它确实不包含任何函数模板。fun因此,尝试对 的两个重载进行参数推导func,结果成功。结果,参数fun变成了非推导上下文,这意味着无法推导任何参数,Ret并且调用失败,因为没有候选者(正是 clang 抱怨的)。

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

call<int>(mutableValue, func)
Run Code Online (Sandbox Code Playgroud)