Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么模板构造函数优先于复制构造函数? #包括 结构 { uct(){std::cerr_C++_Copy Constructor_Overload Resolution_Function Templates_Constructor Overloading - Fatal编程技术网

C++ 为什么模板构造函数优先于复制构造函数? #包括 结构 { uct(){std::cerr

C++ 为什么模板构造函数优先于复制构造函数? #包括 结构 { uct(){std::cerr,c++,copy-constructor,overload-resolution,function-templates,constructor-overloading,C++,Copy Constructor,Overload Resolution,Function Templates,Constructor Overloading,据我所知,在重载解析过程中,非模板函数总是优于模板函数 只有当专门化和非模板完全相同时,这才是正确的。但这里不是这样。当调用uct u3(u1)时,重载集 #include <iostream> struct uct { uct() { std::cerr << "default" << std::endl; } uct(const uct &) { std::cerr << "copy" << std::e

据我所知,在重载解析过程中,非模板函数总是优于模板函数

只有当专门化和非模板完全相同时,这才是正确的。但这里不是这样。当调用
uct u3(u1)
时,重载集

#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?
}
现在,由于
u1
不是常量,它必须应用常量转换来调用复制构造函数。要调用模板专门化,它不需要做任何事情,因为它是精确匹配的。这意味着模板获胜,因为它是更好的匹配

要停止此操作,可以使用将模板函数限制为仅在
T
不是
uct
时调用

uct(const uct &)
uct(uct &) // from the template
模板,bool>=true>

uct(T&&{std::cerr问题是模板构造函数没有限定符
const
,而非模板副本构造函数的参数中有限定符const。如果将对象
u1
声明为
const
对象,则将调用非模板副本构造函数

<> >从C++标准(7标准转换)< /P> 1标准转换是具有内置含义的隐式转换。 第7条列举了所有此类转换。标准 “转换序列”是中的标准转换序列 顺序如下:

(1.4)零或一次资格转换

因此,复制构造函数需要一个标准转换,而模板构造函数SIE不需要这样的转换

当试图调用复制构造函数时,模板重载被禁用 选择。据我所知,非模板函数总是首选 重载解析期间的模板函数。为什么复制构造函数 处理方式不同


再加上,这就是为什么模板构造函数是奇怪的野兽,除非你想让它们超越一切,否则你可能想标记构造函数。(类似于
inplace\t
)@SergeyA或使用SFINAE.或其他,但标记通常更容易添加
const
将前向引用转换为右值引用。因此,由于非模板与模板规则的不同,它不是首选,而是因为
uct u3(u1)
在允许的情况下不匹配加载任何接收转发参考的函数都是令人担忧的。“转发太完美了”。在这个问题中没有基于意见的内容。为什么VTC是POB?
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; }
template <typename T>
uct(T &&) { std::cerr << "template" << std::endl; }
//    ^^
template <typename T, std::enable_if_t<!std::is_same_v<std::decay_t<T>, uct>>>
uct(T&&)
{
  std::cerr << "template" << std::endl;
}