[英]Class with templated constructor as well as copy and move constructor
这个问题是该问题的后续解决方案: 模板类的模板构造函数的显式模板专业化当然,另一个问题给出的答案是正确的,但事实证明我并没有问自己想问的问题-所以这是一个新问题:
考虑以下代码:
template<typename First, typename ... Rest> class var {
public:
var() {
std::cout << "default" << std::endl;
}
var(const var& v) {
std::cout << "copy" << std::endl;
}
var(var&& v) {
std::cout << "move" << std::endl;
}
template<typename T>
var(const T& t) {
std::cout << "general lvalue" << std::endl;
}
template<typename T>
var(T&& t) {
std::cout << "general rvalue" << std::endl;
}
};
int main()
{
var<int> i0; // expect 'default' -> get 'default'
var<int> i1(i0); // expect 'copy' -> get 'general rvalue'
var<int> i2(std::move(i0)); // expect 'move' -> get 'move'
std::string s("Hello");
var<int> i3(s); // expect 'general lvalue' -> get 'general rvalue'
var<int> i4(std::move(s)); // expect 'general rvalue' -> get 'general rvalue'
}
我在main函数中编写了我期望并希望调用的构造函数以及实际调用的构造函数。 这是我的问题:
1)您能解释为什么该程序无法正常运行吗?
2)如何使程序在调用var时调用var的复制并移动构造函数,否则要调用模板化的构造函数?
3)最后,我试图将两个模板化的构造函数放到一个同时处理左值和右值的函数中,并使用std :: forward将它们转发到另一个函数-看起来如何?
1)您能解释为什么该程序无法正常运行吗?
在这行上:
var<int> i1(i0); // expect 'copy' -> get 'general rvalue'
var(T&&)
构造函数由T
实例化,该T
替换为var<int>&
,即生成具有以下签名的构造函数:
var(var&);
该构造函数比隐式副本构造函数var(const var&)
更好,因为i0
是非常数。
同样适用于:
var<int> i3(s); // expect 'general lvalue' -> get 'general rvalue'
s
是非常量的,因此用T
实例化var(T&&)
构造函数,并用std::string&
替换T
,从而生成具有签名的构造函数:
var(std::string&);
对于非常量参数,构造函数比其他构造函数模板更好地匹配,后者产生:
var(const std::string&);
您需要认识到var(T&&)
构造函数不是“常规rvalue”构造函数,因为T&&
可以匹配包括lvalues在内的任何类型。
有关更多详细信息,请参见C ++ 11中的通用参考 。
2)如何使程序在调用var时调用var的复制并移动构造函数,否则要调用模板化的构造函数?
约束模板,使它们不接受任何类型。
template<typename T>
using Is_a_var = std::is_same<typename std::decay<T>::type, var>;
template<typename T>
using Enable_if_not_a_var = typename std::enable_if<!Is_a_var<T>::value>::type;
template<typename T, typename Constraint = Enable_if_not_a_var<T>>
var(T&& t) {
std::cout << "general value" << std::endl;
}
我还将添加默认的copy / move构造函数,以使想要的读者清楚:
var(const var&) = default;
var(var&&) = default;
3)最后,我试图将两个模板化的构造函数放到一个同时处理左值和右值的函数中,并使用std :: forward将它们转发到另一个函数-看起来如何?
别。 var(T&&)
构造函数已经接受了rvalue 和 lvalues。
使用std:forward<T>(t)
将参数转发给其他函数:
template<typename T, typename Constraint = Enable_if_not_a_var<T>>
var(T&& t) : m_something(std::forward<T>(t)) {
std::cout << "general value" << std::endl;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.