我正在尝试设计一个具有两个大序列向量的类。
std::vector<double> factory() {
return std::vector<double>{1,2,3}; // it actually generates a large sequence of double
}
struct my_class {
my_class(const std::vector<double>& x, const std::vector<double>& y)
: m_x(x), m_y(y)
{ }
std::vector<double> m_x;
std::vector<double> m_y;
};
int main() {
my_class c(factory(), factory());
my_class c2(factory(), {0.5, 1, 1.5});
}
嗯,它运行良好,但它不使用向量的移动构造函数。所以我试图改变构造函数以接受具有完美转发的r值引用。
struct my_class {
template<typename X, typename Y>
my_class(X&& x, Y&& y
, typename std::enable_if<std::is_convertible<X, std::vector<double> >::value &&
std::is_convertible<Y, std::vector<double> >::value>::type * = 0
)
: m_x(std::forward<X>(x)), m_y(std::forward<Y>(y))
{ }
std::vector<double> m_x;
std::vector<double> m_y;
};
现在我遇到了问题。当我尝试使用initializer_list构造一个实例时,我得到了这样的错误。
$ g++ -W -Wall -std=gnu++0x a.cpp
a.cpp: In function ‘int main()’:
a.cpp:34:32: error: no matching function for call to ‘my_class::my_class(std::vector<double>, <brace-enclosed initializer list>)’
a.cpp:17:18: note: candidate is: my_class::my_class(const my_class&)
我认为std::initializer_list<double>
可能无法转换为std::vector<double>
,但它实际上是可转换的,当我尝试没有enable_if参数时,我得到了同样的错误。我错过了什么吗?
答案 0 :(得分:7)
首选成语是pass by value,然后在成员初始化列表中手动移动:
struct my_class {
my_class(std::vector<double> x, std::vector<double> y)
: m_x(std::move(x)), m_y(std::move(y))
{ }
std::vector<double> m_x;
std::vector<double> m_y;
};
这将适用于所有可能的论点并且速度相当快:
x
,然后移至m_x
。x
,然后再次移至m_x
。x
将从该列表初始化,然后移至m_x
。替代方案是完美转发,但这使得客户更难以了解他可能传递的内容:
struct my_class {
template<typename T, typename U>
my_class(T&& x, U&& y)
: m_x(std::forward<T>(x)), m_y(std::forward<U>(y))
{ }
std::vector<double> m_x;
std::vector<double> m_y;
};
另外,我在g ++中收到一堆警告,所以我不推荐它。只是提到它的完整性。