c – 使用单参数模板化构造函数构造引用元组的值元组
我有一个const引用的元组std :: tuple< const Matrix&,...>我从中构造了一个值元组std :: tuple< Matrix,...>.对于大于1的任何大小的元组,这都可以正常工作:(在线示例:
https://godbolt.org/g/24E8tU)
#include <tuple> struct Matrix { Matrix() = default; Matrix(Matrix const&) = default; template <typename T> explicit Matrix(T const&) { // in reality,this comes from Eigen,and there is real work // being done here. this is just to demonstrate that the code // below fails static_assert(std::is_same<T,int>::value,"!"); } }; void works() { Matrix m1,m2; std::tuple<const Matrix &,const Matrix &> tuple_of_ref{m1,m2}; std::tuple<Matrix,Matrix> t{tuple_of_ref}; } 但是,对于大小为1的元组,此代码无法编译: void fails() { Matrix m; std::tuple<const Matrix &> tuple_of_ref{m}; // Tries and fails to instantiate Matrix(std::tuple<const Matrix &>) std::tuple<Matrix> t{tuple_of_ref}; } 注意Matrix类有一个模板化的构造函数,它接受std :: tuple.
我不想使用这个构造函数,因为它是第三方代码,所以我无法更改它. 我认为我的works()示例正确调用cppreference上列为#4的构造函数:
failed()示例尝试使用this constructor,大概是#3,我不想要:
如何确保元组的构造函数#4用于两种情况?我的真实用例是在一个可变参数模板中,所以我不知道提前元组的大小. 解决方法
是的,所以……这就是问题所在:
template<typename T> explicit Matrix(const T& x) 这是一个非常不友好的构造函数 – 因为它在说谎.矩阵实际上不是可以从任何东西构建的,只是某些特定的东西 – 但是没有办法从外部检测这些东西是什么. 在考虑如何构造元组< Matrix>时从一个元组< Matrix const&>,我们有lots of choices,但实际上只有两个是可行的: // #2,with Types... = {Matrix} tuple(Matrix const&); // #3,with UTypes = {tuple<Matrix const&>&} tuple(tuple<Matrix const&>&); 两人最终都试图从元组< Matrix const&>构造一个矩阵,这不起作用而且你被卡住了. 现在,你可能会认为#4是你的救赎 – 生成一个构造函数: tuple(tuple<Matrix const&> const& ); 并从元组参数的底层Matrix构造其基础Matrix.也就是说,使用转换复制构造函数.似乎问题在于这个构造函数是有效的,但是#3因为任何原因而首选(即它需要较少的cv限定引用)并且解决方案是试图摆弄参数以便#4是首选(即在参数上使用as_const()). 但是这个构造函数并不是优先考虑的……它实际上不可行,因为that constructor is的限制(从LWG 2549开始):
但是我们确实有sizeof ..(类型)== 1并且那些东西都不是假的(尤其是第二个是真的 – 这是你开始时遇到的所有问题的根源),所以#4根本就不是候选人,并没有一个巧妙的技巧,只是让它成为一个. 那么,如何解决呢?到目前为止,最好的办法是修复Matrix.我意识到这可能不太可能,但必须要说. 您可以将Matrix包装在实际为其构造函数添加约束的内容中以避免此问题.既然你已经将它复制到一个元组中,那么你就有机会做一些简单的事情: template <typename T> struct only_copyable { only_copyable(only_copyable const& ) = default; only_copyable(T const& t) : t(t) { } template <typename U> only_copyable(U const& ) = delete; T t; }; 但你可能想要比这更现实的东西.你的类型也可以继承Matrix,只是为了理智而摆弄它的构造函数. 或者,在专门处理大小为1的元组时,可以避免使用元组构造函数,只需使用默认的构造/赋值.或者明确地调用get< 0>或者那种东西. 或者,您可以完全避免使用大小为1的元组.这是一个奇怪的具体事情,但也许这就足够了(或者你可以用my_tuple< A,B,C ......>是元组< A,C ......>来包装元组但是my_tuple< A>实际上是元组< A,monostate>). 但真的……修复Matrix构造函数似乎非常值得. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |