我如何使一个模板化的构造函数允许所有的l值ref, r值ref和initializer_list
How can i make a templated constructor allowing all of l-value ref, r-value ref and initializer_list?
我正在尝试设计一个类,它有两个大序列向量。
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});
}
它工作得很好,但是它没有使用vector的move构造函数。因此,我试图改变构造函数,以接受具有完美转发的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参数尝试时,我得到了同样的错误。我错过什么了吗?
首选的习惯用法是按值传递,然后手动在成员初始化列表中移动:
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++中得到了一堆警告,所以我不推荐它。只是为了完整起见。
相关文章:
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 对RValue对象调用的LValue ref限定成员函数
- 将Ref对象作为类成员
- 如何在 C 中正确使用 libiconv 使其不会报告"Arg list too long"?
- C++中带有List类的迭代器Segfault
- 使用"std::unordereded_map"映射到"std::list"对象
- GCC对可能有效的代码抛出init list生存期警告
- 使用std::list创建循环链表
- 为什么我的 std::ref 无法按预期工作?
- 重载Singly Linked List中的赋值运算符
- 如何将 Eigen::Ref 与 pybind11 一起使用?
- '[](std::list& list)<int>{return std::move(list)}(list)' 是否保证将 'list' 留空?
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?
- 为什么这个 std::queue/指向结构的指针列表直到 List.Size() == 0 才释放内存?
- 如何@ref同一方法的不同变体?
- "std::list::splice(std::const_iterator pos, std::list&& other)"是否保证将"其他"留空?
- 从嵌套循环中的 std::list 中删除将返回访问冲突
- QStringList vs list<shared_ptr<QString>> 性能比较C++
- 使用带有 ref 参数的成员函数创建线程时出现编译错误