来自元组的构造函数参数

Add*_*ddy 6 c++ constructor struct tuples

如果我有一个像这样的结构:

struct Thing
{
  int x;
  int y;
  bool a;
  bool b;
}
Run Code Online (Sandbox Code Playgroud)

然后我可以通过以下方式创建一个Thing对象:Thing t {1,2,true,false};.但是,如果我有一个元组,那么我正在做类似的事情:

std::tuple<int, int, bool, bool> info = std::make_tuple(1,2,true,false);
Thing t { std::get<0>(info), std::get<1>(info).. // and so on
Run Code Online (Sandbox Code Playgroud)

有一个更好的方法吗?

W.F*_*.F. 6

如果您使用的是 c++14,您可以使用std::index_sequence创建辅助函数和结构,如下所示:

#include <tuple>
#include <utility>

struct Thing
{
  int x;
  int y;
  bool a;
  bool b;
};

template <class Thi, class Tup, class I = std::make_index_sequence<std::tuple_size<Tup>::value>>
struct Creator;

template <class Thi, class Tup, size_t... Is>
struct Creator<Thi, Tup, std::index_sequence<Is...> > {
   static Thi create(const Tup &t) {
      return {std::get<Is>(t)...};
   }
};

template <class Thi, class Tup>
Thi create(const Tup &t) {
   return Creator<Thi, Tup>::create(t);
}

int main() {
   Thing thi = create<Thing>(std::make_tuple(1,2,true,false));
}
Run Code Online (Sandbox Code Playgroud)

以及没有附加类的版本(具有一个附加功能):

#include <tuple>
#include <utility>

struct Thing
{
  int x;
  int y;
  bool a;
  bool b;
};

template <class Thi, class Tup, size_t... Is>
Thi create_impl(const Tup &t, std::index_sequence<Is...>) {
   return {std::get<Is>(t)...};
}

template <class Thi, class Tup>
Thi create(const Tup &t) {
   return create_impl<Thi, Tup>(t, std::make_index_sequence<std::tuple_size<Tup>::value>{});
}

int main() {
   Thing thi = create<Thing>(std::make_tuple(1,2,true,false));
}
Run Code Online (Sandbox Code Playgroud)

这次又是一个棘手的版本,只有一个辅助函数:

#include <tuple>
#include <utility>

struct Thing
{
  int x;
  int y;
  bool a;
  bool b;
};

template <class R, class T, size_t... Is>
R create(const T &t, std::index_sequence<Is...> = {}) {
   if (std::tuple_size<T>::value == sizeof...(Is)) {
      return {std::get<Is>(t)...};
   }
   return create<R>(t, std::make_index_sequence<std::tuple_size<T>::value>{});
}

int main() {
   Thing thi = create<Thing>(std::make_tuple(1,2,true,false));
}
Run Code Online (Sandbox Code Playgroud)

  • 你甚至不需要课程:http://coliru.stacked-crooked.com/a/9d5f6743ace68bdb (2认同)

Bar*_*rry 6

我们可以从元组样类型创建聚集(创建一个通用的工厂函数std::tuple,std::pair,std::array,和任意用户定义的元组就像一个结构化的绑定世界中的物体):

template <class T, class Tuple, size_t... Is>
T construct_from_tuple(Tuple&& tuple, std::index_sequence<Is...> ) {
    return T{std::get<Is>(std::forward<Tuple>(tuple))...};
}

template <class T, class Tuple>
T construct_from_tuple(Tuple&& tuple) {
    return construct_from_tuple<T>(std::forward<Tuple>(tuple),
        std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{}
        );
}
Run Code Online (Sandbox Code Playgroud)

在您的情况下将用作:

std::tuple<int, int, bool, bool> info = std::make_tuple(1,2,true,false);
Thing t = construct_from_tuple<Thing>(info); // or std::move(info)
Run Code Online (Sandbox Code Playgroud)

这样,Thing仍然可以是聚合(不必添加构造函数/赋值),我们的解决方案可以解决许多类型的问题.

作为一项改进,我们可以将SFINAE添加到两个重载中,以确保它们无法使用无效的元组类型进行调用.


†在接受分解如何工作的措辞之前,std::get<Is>可能需要将符合条件的呼叫更改为get<Is>具有特殊查找规则的非限定呼叫.目前,这是没有实际意义,因为它是2016年,我们没有结构化绑定.


更新:在C++ 17中,有std::make_from_tuple().


Dút*_*has 1

提供显式构造函数和赋值运算符:

struct Thing
{
  int x;
  int y;
  bool a;
  bool b;

  Thing() { }

  Thing( int x, int y, bool a, bool b ): x(x), y(y), a(a), b(b) { }

  Thing( const std::tuple <int, int, bool, bool> & t ) 
  {
    std::tie( x, y, a, b ) = t;
  }

  Thing& operator = ( const std::tuple <int, int, bool, bool> & t ) 
  {
    std::tie( x, y, a, b ) = t;
    return *this;
  }
};
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。