转发模板优先于过载 [英] Forwarding template taking precedence over overload
问题描述
我认为,如果参数也匹配,那么非模板将始终优先于模板.
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 invokesTrace(const int&)
. You might also need aTrace(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屋!