gpt4 book ai didi

c++ - 使用单参数模板化构造函数从引用元组构造值元组

转载 作者:太空狗 更新时间:2023-10-29 20:20:35 25 4
gpt4 key购买 nike

我有一个 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 .

template<typename T>
explicit Matrix(const T& x)

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

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

template< class... UTypes >
tuple( const tuple<UTypes...>& other );

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

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

template< class... UTypes >
explicit tuple( UTypes&&... args );

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

我怎样才能确定tuple的构造函数 #4 用于这两种情况?我的真实用例是在可变参数模板中,所以我事先不知道元组的大小。

最佳答案

是的,所以...这就是问题所在:

template<typename T>
explicit Matrix(const T& x)

那是一个非常不友好的构造函数——因为它在撒谎。 Matrix实际上不能从任何东西构造,只是一些特定的东西——但没有办法从外部检测这些东西是什么。

当考虑怎样构建一个tuple<Matrix>来自tuple<Matrix const&> , 我们有 lots of choices , 但实际上只有两个可行:

// #2, with Types... = {Matrix}
tuple(Matrix const&);

// #3, with UTypes = {tuple<Matrix const&>&}
tuple(tuple<Matrix const&>&);

双方最终都试图构建一个 Matrix来自tuple<Matrix const&> ,这是行不通的,你被卡住了。


现在,您可能认为 #4 是您的救星 - 生成一个构造函数:

tuple(tuple<Matrix const&> const& );

并构建其基础Matrix来自 tuple论证的基础 Matrix .也就是说,使用转换复制构造函数。似乎问题在于此构造函数有效,但无论出于何种原因(即它采用较少的 cv 限定引用),#3 都是首选,解决方案是尝试摆弄参数,以便首选 #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..(Types) == 1并且这些事情并非都是错误的(特别是,第二个是正确的 - 这是你所有问题的根源),所以#4根本不是候选人并且没有真正巧妙的技巧可以制作它一个。


那么,如何解决呢? 到目前为止要做的最好的事情就是修复Matrix .我知道这不太可能,但不得不说。

你可以包装 Matrix在实际上向其构造函数添加约束以避免此问题的东西中。由于您已经将其复制到 tuple 中,这让您有机会做一些简单的事情,例如:

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为了理智起见,只是摆弄它的构造函数。

或者,在专门处理 tuple 时s 的大小为 1,您可以避免使用元组构造函数而只使用默认构造/分配。或者显式调用 get<0>或类似的东西。

或者,您可以避免 tuple s 大小 1 完全。这是一件奇怪的具体事情,但也许这就足够了(或者你可以包装 tuple 使得 my_tuple<A, B, C...>tuple<A,B,C...>my_tuple<A> 实际上是 tuple<A, monostate> )。

但真的...修复 Matrix构造函数似乎非常值得。

关于c++ - 使用单参数模板化构造函数从引用元组构造值元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49988289/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com