转发模板优先于过载 [英] Forwarding template taking precedence over overload

查看:58
本文介绍了转发模板优先于过载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为,如果参数也匹配,那么非模板将始终优先于模板.

I thought that a non-template would always take precedence over a template, if the arguments match up just as well.

但是:

template <typename... Args>
void Trace(Args&&... args)
{
    throw "what the frak";
}

void Trace(const int&)
{}

int main()
{
    Trace(42);
}

这会抛出,除非我将非模板设为Trace(int)Trace(int&&) ,即不使用const引用.

This throws unless I make the non-template Trace(int) or Trace(int&&), i.e. not taking a const ref.

这很烦人,因为我想为特定参数类型提供不同的实现,而模板的实际实现是没有意义的(实际上是不会编译的).

It's kind of annoying because I want to provide a different implementation for specific argument types where the real implementation of the template does not make sense (and, in fact, would not compile).

我可以通过将第二个函数专门化来解决它,但前提是我通过使用右值引用来匹配参数类型:

I can fix it by making the second function a specialisation, but only if I match argument types by taking an rvalue reference:

template <>
void Trace(int&&)
{}

而且,也许我不想这样做!也许我有时想用const来称呼它,而宁愿不专攻两次.

And, well, maybe I didn't want to do that! Maybe I want to call it with a const thing sometimes and would rather not specialise twice.

在此示例中,仅提供非模板重载以这种方式工作是否正确并且符合标准?这是我第一次注意到这种行为(并非一定意味着任何事情!).

Is it correct and standard-abiding that simply providing a non-template overload works this way, in this example? It's the first time I've noticed this behaviour (not that that necessarily means anything!).

推荐答案

42是类型int的右值,因此它与int&&的绑定更紧密,而不是与const int&的绑定.这就是为什么它正在调用您的模板Trace函数.

42 is an rvalue of type int, therefore it binds more closely to int&& rather than const int&. This is why it is calling your template Trace function.

如果您要致电

const int i{};
Trace(i);

然后将调用您的Trace(const int&)重载.

可能的解决方法:

  • 添加一个调用Trace(const int&)Trace(int&&)重载.您可能还需要Trace(int&);

  • Add a Trace(int&&) overload that invokes Trace(const int&). You might also need a Trace(int&);

在模板化的Trace上使用SFINAE防止在第一个参数为int时实例化;

Use SFINAE on the templated Trace to prevent instantiation when the first argument is an int;

template <typename Arg, typename... Args>
auto Trace(Arg&& arg, Args&&... args)
    -> std::enable_if_t<!std::is_same_v<std::decay_t<Arg>, int>>
{
    throw "what the frak";
}   

  • 更改模板化的Trace以改为使用const Args&....

  • Change the templated Trace to take const Args&... instead.

    这篇关于转发模板优先于过载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆