使用具有两个或多个参数的类初始化 std::tuple

Dan*_*Lee 11 c++ stdtuple c++14

#include <iostream>

class NoCopyMove {
public:
    NoCopyMove(int a) : a_(a), b_(a) {}
    NoCopyMove(int a, int b) : a_(a), b_(b) {}

    NoCopyMove(const NoCopyMove&) = delete;
    NoCopyMove& operator=(const NoCopyMove&) = delete;
    NoCopyMove(NoCopyMove&&) = delete;
    NoCopyMove& operator=(NoCopyMove&&) = delete;

    int a_;
    int b_;
};

int main()
{
    std::tuple<NoCopyMove, NoCopyMove> t {6, 9};
    std::cout << std::get<0>(t).a_ << std::endl;   
    std::tuple<NoCopyMove, NoCopyMove> t2 {{6, 7}, {8, 9}};
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试创建一个具有两个以上参数作为构造函数的类元组。如果只有一个构造函数参数,它就可以工作。

main.cpp:45:28: error: no matching constructor for initialization of 'std::tuple<NoCopyMove>'
    std::tuple<NoCopyMove> t2 {{6, 7}, {8, 9}}};
                           ^  ~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

可能需要对编译器进行某种提示,但我不知道如何做到这一点。任何类型的关键字和提示将不胜感激。

chr*_*nte 12

除了无关的右大括号之外,您无法构造像这样的不可复制和不可移动类型的元组。std::tuple不支持分段或“放置式”构造,并且正如评论中提到的,它也不是聚合,因此它需要复制或移动各个元素就位。您期望在这里选择的构造函数是通过引用 cppreference 获取元组中的每种类型的const &构造函数

仅当 sizeof...(Types) >= 1 且std::is_copy_constructible::value 对于所有 i 为 true 时,此重载才参与重载决策。

然而,您的类型不可复制构造,因此如果这确实是您需要做的,那么您就不走运了。


Jar*_*d42 9

std::tuple<NoCopyMove, NoCopyMove> t2 {{6, 7}, {8, 9}}};
Run Code Online (Sandbox Code Playgroud)

实际上是

std::tuple<NoCopyMove, NoCopyMove> t2 {NoCopyMove{6, 7}, NoCopyMove{8, 9}}};
Run Code Online (Sandbox Code Playgroud)

因此需要移动或复制构造函数。

在 C++17 中,强制复制省略,带有额外层

template <typename... Ts>
struct Args
{
    Args(Ts... args) : tuple{std::forward<Ts>(args)...} {}

    template <typename T>
    operator T() && { return std::make_from_tuple<T>(std::move(tuple)); }

private:
    std::tuple<Ts...> tuple;
};

template <typename... Ts>
Args(Ts&&...) -> Args<Ts&&...>;
Run Code Online (Sandbox Code Playgroud)

你可能会这样做:

std::tuple<NoCopyMove, NoCopyMove> t2 {Args{6, 7}, Args{8, 9}}};
Run Code Online (Sandbox Code Playgroud)

演示

所以你可以NoCopyMove从就地构建Args{..}