【问题标题】:Distinguish between function references/pointers accepting const and non-const argument with same name as function parameter区分接受与函数参数同名的 const 和非 const 参数的函数引用/指针
【发布时间】:2020-01-24 09:44:59
【问题描述】:

让我们考虑两个同名的函数:

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&amp; 很容易。删除 const Arg&amp; 过载并没有帮助。

【问题讨论】:

  • 尝试改用template&lt;typename Arg, typename Callable&gt; void call(Arg&amp; val, Callable fun) { fun(val); }
  • @RemyLebeau 这没有任何帮助,因为 func(int&amp;)func(const int&amp;) 都匹配 Callable...
  • Ret 可以推导出来,还是decay_t&lt;Arg&gt;(&amp;fun)(Arg&amp;) ok?
  • 在实际用例中Rets 与Args 不同。在func 的情况下它们是相同的只是巧合。
  • 您可以在电话中提供吗? (是这样,你可能有一个解决方案)。如果一定要推演,恐怕你无法解决歧义。

标签: c++ templates metaprogramming


【解决方案1】:

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

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

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

call<int>(mutableValue, func)

【讨论】:

  • 关闭但不完全。对于函数调用,逐个参数分别进行推导。然后在过程结束时合并结果。这意味着不存在“否则失败”的情况。两个推论都微不足道地成功,这使得参数成为非推导上下文。
  • @T.C.感谢您指出了这一点。我的理解是,当该段落提到“参数推导成功”时,它意味着函数模板的参数推导作为一个整体成功,在这种情况下,从参数到单独的函数参数的冲突推导可能会使该推导失败,然后可能从考虑中排除过载。但是,在重新阅读相关部分之后,我想你是对的。我更新了我的答案来解决这个问题……
【解决方案2】:

因为在一个模板参数推导中似乎不可能解决歧义:

如果您对调用站点的语法更改感到满意,您可以将调用分成两个调用/扣除通道:

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

被称为

call(mutableValue)(func)

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

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

【讨论】:

    猜你喜欢
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 2018-09-02
    • 2012-02-25
    • 2013-04-06
    • 2020-01-03
    相关资源
    最近更新 更多