c – 使用单参数模板化构造函数构造引用元组的值元组

c – 使用单参数模板化构造函数构造引用元组的值元组,第1张

概述我有一个const引用的元组std :: tuple< const Matrix&,...>我从中构造了一个值元组std :: tuple< Matrix,...>.对于大于1的任何大小的元组,这都可以正常工作:(在线示例: https://godbolt.org/g/24E8tU) #include <tuple>struct Matrix { Matrix() = default; 我有一个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.

06002

我不想使用这个构造函数,因为它是第三方代码,所以我无法更改它.

我认为我的works()示例正确调用cppreference上列为#4的构造函数:

06003

4) Converting copy-constructor. For all i in sizeof...(UTypes),initializes ith element of the tuple with std::get<i>(other).

Failed()示例尝试使用this constructor,大概是#3,我不想要:

06004

3) Converting constructor. Initializes each element of the tuple with the corresponding value in std::forward<Utypes>(args).

如何确保元组的构造函数#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开始):

either sizeof...(Types) != 1,or (when Types... expands to T and UTypes... expands to U) is_­convertible_­v<const tuple<U>&,T>,is_constructible_­v<T,const tuple<U>&>,and is_­same_­v<T,U> are all false.

但是我们确实有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构造函数似乎非常值得.

总结

以上是内存溢出为你收集整理的c – 使用单参数模板化构造函数构造引用元组的值元组全部内容,希望文章能够帮你解决c – 使用单参数模板化构造函数构造引用元组的值元组所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/1212000.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-04
下一篇 2022-06-04

发表评论

登录后才能评论

评论列表(0条)

保存