C++ 结构化绑定和绑定()

C++ 结构化绑定和绑定(),c++,c++17,structured-bindings,C++,C++17,Structured Bindings,鉴于这些声明: int a[3] {10,20,30}; std::tuple<int,int,int> b {11,22,33}; 但是如果x1,y1等已经存在,我该怎么办 std::tie(x1,y1,z1) = a; // ERROR std::tie(x2,y2,z2) = b; // OK 这适用于b,但不适用于a。是否有类似的简单构造适用于a,或者我必须分别获取a[0]、a[1]和a[2] 结构化绑定具有处理数组和某些其他类型的特定语言规则tie()是一个特定的元

鉴于这些声明:

int a[3] {10,20,30};
std::tuple<int,int,int> b {11,22,33};
但是如果
x1
y1
等已经存在,我该怎么办

std::tie(x1,y1,z1) = a;  // ERROR
std::tie(x2,y2,z2) = b;  // OK
这适用于
b
,但不适用于
a
。是否有类似的简单构造适用于
a
,或者我必须分别获取
a[0]
a[1]
a[2]

结构化绑定具有处理数组和某些其他类型的特定语言规则
tie()
是一个特定的
元组
,只能从另一个
元组
分配


对于数组大小写,您可以编写一个函数,将该数组转换为引用的元组:

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
模板
自动作为元组执行(T(&arr)[N],标准::索引序列){
return std::forward_as_tuple(arr[Is]…);
}
模板
自动作为元组(T(&arr)[N]){
返回为tuple_impl(arr,std::make_index_sequence{});
}
std::tie(x1,y1,z1)=作为元组(a);//好啊

或者,如果您知道有多少绑定(无论如何都必须知道),可以使用结构化绑定作为返回元组的方法。但您必须指定尺寸,并为每个尺寸写一个案例:

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
模板
自动作为元组(T&&tuple){
如果constexpr(I==1){
auto&&[a]=std::forward(元组);
return std::forward_as_tuple(a);
}如果constexpr(I==2),则为else{
auto&&[a,b]=std::forward(元组);
return std::forward_as_tuple(a,b);
}如果constexpr(I==3),则为else{
//等等。
}
}
std::tie(x1,y1,z1)=作为元组(a);//好啊

只是为了好玩。。。要模拟类似于的语法,请执行以下操作:

std::tie(x1,y1,z1) = a;
您可以编写一个结构来包装指针数组,并为相应数组使用
运算符=()

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;
    }
 };
工作

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

#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;
 }
#包括
#包括
#包括
模板
结构光碟;
模板
结构ptrArray
{
std::阵列ap;
自动和操作员=(T(&arr)[sizeof…(Is)])
{
((*ap[Is]=arr[Is]),…);
归还*这个;
}
};
模板
普特拉雷
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在第二种情况下,您不能在
get
上使用SFINAE删除显式大小吗?@passway
get
std::array
不友好,它不是为原始数组定义的(对吗?),并且它肯定不适用于所有公共成员的类型。进一步研究,有一些,这是可能的。@PasserBy聪明,但是…您可以在非聚合的类型上使用结构化绑定:-)
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;
 }