1)你能解释一下为什么程序的行为不符合我的预期吗?
在这一行:
var<int> i1(i0); // expect 'copy' -> get 'general rvalue'
The var(T&&)
构造函数实例化为T
替换为var<int>&
,即生成具有此签名的构造函数:
var(var&);
该构造函数比隐式复制构造函数更匹配var(const var&)
因为i0
是非常量。
同样对于:
var<int> i3(s); // expect 'general lvalue' -> get 'general rvalue'
s
是非常量,所以var(T&&)
构造函数实例化为T
替换为std::string&
,生成一个带有签名的构造函数:
var(std::string&);
对于非常量参数,构造函数比其他构造函数模板更匹配,它会生成:
var(const std::string&);
您需要意识到var(T&&)
构造函数不是“通用右值”构造函数,因为T&&
可以匹配任何类型包括左值.
See C++11 中的通用引用更多细节。
2)如何让程序在获取 var 时调用 var 的复制和移动构造函数,否则调用模板化构造函数?
限制模板,使其不接受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;
}
我还会添加默认的复制/移动构造函数,以便读者清楚地了解您想要它们:
var(const var&) = default;
var(var&&) = default;
3)最后,我试图将两个模板化构造函数放入一个处理左值和右值的构造函数中,并使用 std::forward 将它们转发到另一个函数 - 这看起来怎么样?
不。这var(T&&)
构造函数已经接受两个右值and左值。
Use 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;
}