结构化结合和绑带()



给定以下声明:

int a[3] {10,20,30};
std::tuple<int,int,int> b {11,22,33};

我可以使用结构化的绑定声明来解码ab

auto [x1,y1,z1] = a;
auto [x2,y2,z2] = b;

但是,如果x1y1等已经存在,我该怎么办?

std::tie(x1,y1,z1) = a;  // ERROR
std::tie(x2,y2,z2) = b;  // OK

这适用于b,但对a不起作用。是否有适用于a的类似简单构造,或者我必须单独获取a[0]a[1]a[2]

nope。

结构化绑定具有特定的语言规则来处理数组和某些其他类型。tie()是专门的tuple<T&...>,只能从另一个tuple<U&...>分配。


使用数组情况,您可以写一个功能将数组变成参考的元组:

template <typename T, size_t N, size_t... Is>
auto as_tuple_impl(T (&arr)[N], std::index_sequence<Is...>) {
    return std::forward_as_tuple(arr[Is]...);
}
template <typename T, size_t N>
auto as_tuple(T (&arr)[N]) {
    return as_tuple_impl(arr, std::make_index_sequence<N>{});
}
std::tie(x1, y1, z1) = as_tuple(a); // ok

另外,如果您知道有多少个绑定(无论如何您都必须(,则可以将结构化的绑定用作借助元组。但是您必须既指定大小又为每个尺寸写出一个案例:

template <size_t I, typename T>
auto as_tuple(T&& tuple) {
    if constexpr (I == 1) {
        auto&& [a] = std::forward<T>(tuple);
        return std::forward_as_tuple(a);
    } else if constexpr (I == 2) {
        auto&& [a, b] = std::forward<T>(tuple);
        return std::forward_as_tuple(a, b);
    } else if constexpr (I == 3) {
        // etc.
    }
}
std::tie(x1, y1, z1) = as_tuple<3>(a); // ok

只是为了娱乐...模拟类似于

的语法
std::tie(x1,y1,z1) = a;

您可以编写包裹一系列指针的结构,并用operator=()用于相应的数组

template <typename T, std::size_t ... Is>
struct ptrArray<T, std::index_sequence<Is...>>
 {
   std::array<T*, sizeof...(Is)> ap;
   auto & operator= (T (&arr)[sizeof...(Is)])
    {
      ((*ap[Is] = arr[Is]), ...);
      return *this;
    }
 };

和该结构的功能

template <typename T0, typename ... Ts>
ptrArray<T0, std::make_index_sequence<sizeof...(Ts)+1U>>
   makePtrArray (T0 & t0, Ts & ... ts)
 { return { { { &t0, &ts... } } }; }

makePtrArray(x1, y1, z1) = a;

工作。

以下是一个完整的工作示例

#include <array>
#include <iostream>
#include <type_traits>
template <typename, typename>
struct ptrArray;
template <typename T, std::size_t ... Is>
struct ptrArray<T, std::index_sequence<Is...>>
 {
   std::array<T*, sizeof...(Is)> ap;
   auto & operator= (T (&arr)[sizeof...(Is)])
    {
      ((*ap[Is] = arr[Is]), ...);
      return *this;
    }
 };
template <typename T0, typename ... Ts>
ptrArray<T0, std::make_index_sequence<sizeof...(Ts)+1U>>
   makePtrArray (T0 & t0, Ts & ... ts)
 { return { { { &t0, &ts... } } }; }
int main ()
 {
   int x1, y1, z1;
   int a[3] {10,20,30};
   makePtrArray(x1, y1, z1) = a;
   std::cout << x1 << ' ' << y1 << ' ' << z1 << std::endl;
 }

最新更新