类与模板构造函数以及复制和移动构造函数 [英] Class with templated constructor as well as copy and move constructor
问题描述
此问题是此问题的后续操作:显式模板类的模板化构造函数的模板专门化
在另一个问题中给出的答案当然是正确的,但结果是我不是在问我想问什么 - 所以这里是一个新问题:
This question is a follow up to this one: Explicit template specialization for templated constructor of templated class The answers given in the other question are of course right but it turned out that I was not quite asking what I wanted to ask - so here is a new question:
请考虑以下代码:
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'
}
我在主函数中写道,想要被调用和哪些被实际调用。这里是我的问题:
I wrote in the main function which constructors I expect and want to be called and which ones are actually called. Here are my questions:
1)你能解释为什么程序不按预期的行为?
1) Can you explain why the program does not behave as I expected?
2)如何让程序调用var的复制和移动构造函数,当它得到一个var和模板化的构造函数?
2) How can I make the program to call the copy and move constructor of var when it gets a var and the templated constructors otherwise?
3)最后,我试图将两个模板化构造函数放入一个处理左值和右值,并将它们转发到另一个函数使用std :: forward - 如何
3) And finally, I'm trying to put the two templated constructors into one handling both lvalues and rvalues and forwarding them to another function using std::forward - how could this look like?
推荐答案
1)你能解释为什么程序不像我预期?
1) Can you explain why the program does not behave as I expected?
在此行上:
var< int> i1(i0); // expect'copy' - > get'general rvalue'
var(T& / code>构造函数被
T
实例化,替换为 var< int>&
具有此签名:
The var(T&&)
constructor is instantiated with T
substituted with var<int>&
, i.e. producing a constructor with this signature:
var(var&);
这个构造函数比隐式拷贝构造函数更好匹配 var ;)
因为 i0
是非常数。
That constructor is a better match than the implicit copy constructor var(const var&)
because i0
is non-const.
>
Similarly for:
var< int> i3(s); // expect'general lvalue' - > get'general rvalue'
s
非const,因此 var(T&&)
构造函数用 T
c> std :: string& ,生成带有签名的构造函数:
s
is non-const, so the var(T&&)
constructor is instantiated with T
substituted with std::string&
, producing a constructor with the signature:
var(std::string&);
对于非const参数,构造函数比其他构造函数模板更好的匹配,
For a non-const argument that constructor is a better match than the other constructor template, which produces:
var(const std::string&);
您需要意识到 var(T&& code>构造函数不是一般右值构造函数,因为
T&&&
可以匹配任何类型包括lvalue 。
You need to realise that the var(T&&)
constructor is not a "general rvalue" constructor, because T&&
can match any type including lvalues.
请参阅在C ++ 11中的通用引用更多细节。
2)如何让程序调用副本
2) How can I make the program to call the copy and move constructor of var when it gets a var and the templated constructors otherwise?
限制模板,因此它们不接受任何类型。
Constrain the templates so they don't accept any type.
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;
}
我还会添加默认的复制/移动构造函数,想要他们:
I would also add defaulted copy/move constructors, to be clear to readers you want them:
var(const var&) = default;
var(var&&) = default;
3)最后,我试图将两个模板构造函数转换为一个处理左值和右值,并将它们转发到另一个函数使用std :: forward - 这怎么可能?
3) And finally, I'm trying to put the two templated constructors into one handling both lvalues and rvalues and forwarding them to another function using std::forward - how could this look like?
Don 't。 var(T&&)
构造函数已经接受了两个右值和左值。
Don't. The var(T&&)
constructor already accepts both rvalues and lvalues.
使用 std:forward< T>(t)
将参数转发到其他函数:
Use std:forward<T>(t)
to forward the argument to other functions:
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;
}
这篇关于类与模板构造函数以及复制和移动构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!