为什么模板构造函数比复制构造函数更受青睐? [英] Why is template constructor preferred to copy constructor?

查看:140
本文介绍了为什么模板构造函数比复制构造函数更受青睐?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#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?
}

大肠菌

构造函数的模板重载适合两个声明(u2u3).但是,当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屋!

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