为什么模板构造函数比复制构造函数更受青睐? [英] Why is template constructor preferred to copy constructor?
问题描述
#include <iostream>
struct uct
{
uct() { std::cerr << "default" << std::endl; }
uct(const uct &) { std::cerr << "copy" << std::endl; }
uct( uct&&) { std::cerr << "move" << std::endl; }
uct(const int &) { std::cerr << "int" << std::endl; }
uct( int &&) { std::cerr << "int" << std::endl; }
template <typename T>
uct(T &&) { std::cerr << "template" << std::endl; }
};
int main()
{
uct u1 ; // default
uct u2( 5); // int
uct u3(u1); // template, why?
}
构造函数的模板重载适合两个声明(u2
和u3
).但是,当int
传递给构造函数时,将选择非模板重载.调用复制构造函数时,将选择模板重载.据我所知,在重载解析期间,非模板函数总是比模板函数更受青睐.为什么复制构造函数的处理方式不同?
Template overload of the constructor fits to both declarations (u2
and u3
). But when int
is passed to the constructor, a non-template overload is chosen. When the copy constructor is called, a template overload is chosen. As far as I know, a non-template function is always preferred to a template function during overload resolution. Why is the copy constructor handled differently?
推荐答案
据我所知,在重载解决方案中,非模板功能总是比模板功能更受欢迎.
As far as I know non-template function is always preferred to template function during overload resolution.
仅当专业化和非模板完全相同时,这是正确的.但是,这里不是这种情况.当您调用uct u3(u1)
重载集时会得到
This is true, only when the specialization and the non template are exactly the same. This is not the case here though. When you call uct u3(u1)
The overload sets gets
uct(const uct &)
uct(uct &) // from the template
现在,由于u1
不是const,因此必须应用const转换才能调用复制构造函数.要调用模板专业化,它是完全匹配的,因此无需执行任何操作.这意味着模板将胜出,因为它是更好的匹配.
Now, since u1
is not const it would have to apply a const transformation to call the copy constructor. To call the template specialization it needs to do nothing since it is an exact match. That means the template wins as it is the better match.
要停止此操作,您可以使用 SFINAE 进行限制仅当T
不是uct
时才调用模板函数.看起来像
To stop this one thing you can do is use SFINAE to limit the template function to only be called when T
is not a uct
. That would look like
template <typename T, std::enable_if_t<!std::is_same_v<uct, std::decay_t<T>>, bool> = true>
uct(T &&) { std::cerr << "template" << std::endl; }
这篇关于为什么模板构造函数比复制构造函数更受青睐?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!