3

我需要将元组的值转发给成员初始化程序:

struct Struct {
  Member1 member1;
  Member2 member2;

  template<typename Tuple1, typename Tuple2>
    Struct( Tuple1&& tuple1, Tuple2&& tuple2 )
      : member1(tuple1...), member2(tuple2...)
    {}
};

上面的代码显然是无效的。我该如何表达?

Member1并且Member2没有默认/复制/移动构造函数。

我知道std::apply,正如如何将元组扩展为可变参数模板函数的参数中所建议的那样?. 我也知道std::make_from_tuple。但我不知道如何在成员初始化程序中使用这些。

任何 C++ 标准都可以(最好是 C++17,但 C++20 也可以)。

澄清一下,我的真正目标是创建一个Struct,将两组可变参数传递给它以完美转发它们以初始化member1member2。我认为将这两个集合“分组”为元组可能是一个好主意,因为这就是这样std::map::emplace做的。其他方法也可以工作(例如,在两组可变参数之间传递一个特殊对象)。

4

2 回答 2

4

std::make_from_tuple确实是正确的选择:

#include <tuple>
struct Member1 {
    Member1(int x,float y, char z){}

    Member1(const Member1& other)=delete;
    Member1(Member1&& other)=delete;
};

struct Member2 {
    Member2(int x,float y, char z){}

    Member2(const Member2& other)=delete;
    Member2(Member2&& other)=delete;
};

struct Struct {
  Member1 member1;
  Member2 member2;

  template<typename Tuple1, typename Tuple2>
    Struct(Tuple1&& tuple1, Tuple2&& tuple2)
      : member1(std::make_from_tuple<Member1>(std::forward<Tuple1>(tuple1))),
       member2(std::make_from_tuple<Member2>(std::forward<Tuple2>(tuple2)))
    {}
};

int main(){
    Struct c(std::tuple{1,1.1,'c'},std::tuple{2,2.2,'x'});
}

神螺栓演示

于 2020-12-24T23:29:55.900 回答
3

cppreference.com有一个很好的示例实现示例std::make_from_tuple,但是,您发现由于缺少底层类的复制构造函数,您无法使用它。

但是,它的面包屑可让您对其进行调整以解决这些限制:

#include <tuple>
#include <iostream>

struct Member1 {
    Member1(int a, int b)
    {
        std::cout << a << " "
              << b
              << std::endl;
    }

    Member1(const Member1 &)=delete;
    Member1(Member1 &&)=delete;
};

struct Member2 {
    Member2(const char *str)
    {
        std::cout << str << std::endl;
    }

    Member2(const Member2 &)=delete;
    Member2(Member2 &&)=delete;
};

// De-obfucation shortcut

template<typename Tuple>
using make_index_sequence_helper=std::make_index_sequence
    <std::tuple_size_v<std::remove_reference_t<Tuple>>>;

struct Struct {
    Member1 member1;
    Member2 member2;

    template<typename Tuple1, typename Tuple2>
    Struct( Tuple1&& tuple1,
        Tuple2&& tuple2 )
        : Struct{std::forward<Tuple1>(tuple1),
        make_index_sequence_helper<Tuple1>{},
        std::forward<Tuple2>(tuple2),
        make_index_sequence_helper<Tuple2>{}}
    {
    }

    template<typename Tuple1, std::size_t ...tuple1_args,
         typename Tuple2, std::size_t ...tuple2_args>
    Struct(Tuple1 && tuple1,
           std::index_sequence<tuple1_args...>,
           Tuple2 && tuple2,
           std::index_sequence<tuple2_args...>)
        : member1{std::get<tuple1_args>(tuple1)...},
          member2{std::get<tuple2_args>(tuple2)...}
    {
    }
};

int main()
{
    Struct s{ std::tuple<int, int>{2, 3},
        std::tuple<const char *>{"Hello world"}};

    return 0;
}

使用 gcc 10 和-std=c++17.

于 2020-12-24T23:22:33.620 回答