C++ 重载,带有r值引用,类模板的构造函数

C++ 重载,带有r值引用,类模板的构造函数,c++,c++11,C++,C++11,虽然最初似乎是,当通过maker函数调用(以进行模板参数推断)时,存在两个重载,一个是T const&,另一个是T&&: #包括 #包括 #包括 使用名称空间std; // ----------------------------------------------- 样板 结构测试 { m_资源; F m_deleter; 测试(T&&resource、F&&deleter) :m_resource(move(resource)),m_deleter(move(deleter)) { } 测试

虽然最初似乎是,当通过maker函数调用(以进行模板参数推断)时,存在两个重载,一个是
T const&
,另一个是
T&&

#包括
#包括
#包括
使用名称空间std;
// -----------------------------------------------
样板
结构测试
{
m_资源;
F m_deleter;
测试(T&&resource、F&&deleter)
:m_resource(move(resource)),m_deleter(move(deleter))
{
}
测试(T常量和资源,F常量和删除器)
:m_resource(resource),m_deleter(deleter)
{
}
};
// -----------------------------------------------
// -----------------------------------------------
样板
测试(T&T、F&F)
{
返回测试(移动(t)、移动(f));
}
样板
测试(T常数和T,F常数和F)
{
回归试验(t,f);
}
// -----------------------------------------------
int main()
{
//从临时建筑--------------------
Test t(new int,[](int*k){});//确定-构造函数
auto tm=test(新的int,[](int*k){});//确定-maker函数
// -----------------------------------------------
//从l值构造-----------------------
int*N=新的int(24);
自动F=函数([](int*k){});
测试tt(N,F);//正常-构造
自动m=test(N,F);//错误生成器函数
// -----------------------------------------------
返回0;
}

有什么想法吗

我认为这是因为自动类型猜测失败了,因为这行代码说:
prog.cpp:18:2:error:'Test::Test(const T&,const F&)[with T=int*&;F=std::function&]'不能重载
编译器试图用int*&而不是int*实例化它。我很确定,如果您显式地指定类型(我理解您想要避免的),它会工作得很好

我真的不明白你为什么把这个放在你的maker函数中

Test<T, F> test(T&& t, F&& f)
{
    return Test<T, F>(move(t), move(f));
}
测试测试(T&T,F&F)
{
返回测试(移动(t)、移动(f));
}

t
f
已经是右值引用,所以您不需要对它们调用move

我认为这是因为自动类型猜测失败了,因为这行代码说
prog.cpp:18:2:error:'Test::Test(const t&,const f&)[with t=int*&;f=std::function&]'不能重载
编译器尝试使用int*&而不是int*来实例化它。我很确定,如果您显式地指定类型(我理解您想要避免的),它会工作得很好

template<typename T, typename F>
Test<T, F> test(T&& t, F&& f)
{
    return Test<T, F>(move(t), move(f));
}
我真的不明白你为什么把这个放在你的maker函数中

Test<T, F> test(T&& t, F&& f)
{
    return Test<T, F>(move(t), move(f));
}
测试测试(T&T,F&F)
{
返回测试(移动(t)、移动(f));
}
t
f
已经是右值引用,因此不需要对它们调用move

template<typename T, typename F>
Test<T, F> test(T&& t, F&& f)
{
    return Test<T, F>(move(t), move(f));
}
这将接受左值和右值的任意组合,它将确保您返回所需的类型,并且它将使用原始值类别将参数完美地转发给
Test
构造函数

你应该读/看

这将接受左值和右值的任意组合,它将确保您返回所需的类型,并且它将使用原始值类别将参数完美地转发给
Test
构造函数

你应该读/看

int*N
函数F
是左值,因此对于上面的函数模板,
T
被推导出
int*&
F
被推导出
函数&
。引用折叠适用,参数
T&&
变为
int*&&&
,并折叠为
int*&
(与
F&
类似)

因此,使用引用类型(
T==int*&
F==function&
)实例化类模板。在类模板中

Test(T&& resource, F&& deleter)
Test(T const& resource, F const& deleter) 
将产生相同的签名,因为
int*&&&
int*&&const&
都折叠为
int*&
,对于
F
也是如此


请注意,当参数不是常量时,带参数
int*&
的函数比带参数
int*const&
的函数更可取。因此,函数模板

template<typename T, typename F>
Test<T, F> test(T const& t, F const& f)
模板
测试(T常数和T,F常数和F)
不会在出现错误的行中使用。一般来说,通用参考参数非常贪婪

典型的解决方案是使用中所述的完美转发

int*N
函数F
是左值,因此对于上面的函数模板,
T
被推导出
int*&
F
被推导出
函数&
。引用折叠适用,参数
T&&
变为
int*&&&
,并折叠为
int*&
(与
F&
类似)

因此,使用引用类型(
T==int*&
F==function&
)实例化类模板。在类模板中

Test(T&& resource, F&& deleter)
Test(T const& resource, F const& deleter) 
将产生相同的签名,因为
int*&&&
int*&&const&
都折叠为
int*&
,对于
F
也是如此


请注意,当参数不是常量时,带参数
int*&
的函数比带参数
int*const&
的函数更可取。因此,函数模板

template<typename T, typename F>
Test<T, F> test(T const& t, F const& f)
模板
测试(T常数和T,F常数和F)
不会在出现错误的行中使用。一般来说,通用参考参数非常贪婪

典型的解决方案是使用s中所述的完美转发。

t
f
已经是右值引用,因此不需要对它们调用move”
t
f
是变量(变量名称),因此,作为表达式,它们是左值表达式。否则,您可能会意外地离开它们两次。每一个出口