结构化绑定到 const c 数组的副本应该是 const 吗?
Shall structured binding to a copy of a const c-array be const?
考虑这段代码 (demo):
#include <tuple>
#include <type_traits>
struct Ag{int i;int j;};
using T = std::tuple<int,int>;
using Ar = int[2];
const Ag ag {};
const T t {};
const Ar ar {};
void bind_ag(){
auto [i,j] = ag;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_t(){
auto [i,j] = t;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_ar(){
auto [i,j] = ar;
static_assert(std::is_same_v<decltype((i)),int&>); //For GCC
static_assert(std::is_same_v<decltype((i)),const int&>); //For Clang (and standard?)
}
结构化绑定到const
c数组的副本由Clang声明const并且GCC 非常量。
GCC 对 c 数组的行为与观察到的聚合或类似元组类型的行为一致。
另一方面,根据我对标准的阅读,我认为 Clang 遵循所写的内容。在 [dcl.struct.bind]/1 e has type cv A where A is the type of the initializer expression and the cv is the cv-qualifier of the structured binding declaration. And the type of the initializer expression ar
is accordingly to [expr.type]/1 const int[2]
.
应该期待什么?我的意见是 Clang 遵循标准。另一方面,我觉得其意图是数组、聚合和类元组类型的行为是等效的。
[dcl.struct.bind]中标准的措辞说:
If the assignment-expression in the initializer has array type A
and no ref-qualifier is present, e
has type cv A
and each element is copy-initialized or direct-initialized from the corresponding element of the assignment-expression as specified by the form of the initializer.
我们有auto [i,j] = ar;
,ar
有数组类型const int[2]
,标准的写法明确e
有类型const int[2]
。因此,根据措辞,每个绑定引用元素类型 - 即 const int
。 Clang 在技术上是正确的。
然而,正如 Richard Smith 在 gcc bug 80649 中指出的那样:
I think this is a bug in the standard. The cv-qualifiers of the array type should be discarded, as they would be for any normal auto deduction.
看来是对的。当你写 auto x = y;
时,你肯定会认为 x
不是顶级的 const
,但我们这里的情况仍然是。我认为目前还没有针对此的核心问题,但应该有。
考虑这段代码 (demo):
#include <tuple>
#include <type_traits>
struct Ag{int i;int j;};
using T = std::tuple<int,int>;
using Ar = int[2];
const Ag ag {};
const T t {};
const Ar ar {};
void bind_ag(){
auto [i,j] = ag;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_t(){
auto [i,j] = t;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_ar(){
auto [i,j] = ar;
static_assert(std::is_same_v<decltype((i)),int&>); //For GCC
static_assert(std::is_same_v<decltype((i)),const int&>); //For Clang (and standard?)
}
结构化绑定到const
c数组的副本由Clang声明const并且GCC 非常量。
GCC 对 c 数组的行为与观察到的聚合或类似元组类型的行为一致。
另一方面,根据我对标准的阅读,我认为 Clang 遵循所写的内容。在 [dcl.struct.bind]/1 e has type cv A where A is the type of the initializer expression and the cv is the cv-qualifier of the structured binding declaration. And the type of the initializer expression ar
is accordingly to [expr.type]/1 const int[2]
.
应该期待什么?我的意见是 Clang 遵循标准。另一方面,我觉得其意图是数组、聚合和类元组类型的行为是等效的。
[dcl.struct.bind]中标准的措辞说:
If the assignment-expression in the initializer has array type
A
and no ref-qualifier is present,e
has type cvA
and each element is copy-initialized or direct-initialized from the corresponding element of the assignment-expression as specified by the form of the initializer.
我们有auto [i,j] = ar;
,ar
有数组类型const int[2]
,标准的写法明确e
有类型const int[2]
。因此,根据措辞,每个绑定引用元素类型 - 即 const int
。 Clang 在技术上是正确的。
然而,正如 Richard Smith 在 gcc bug 80649 中指出的那样:
I think this is a bug in the standard. The cv-qualifiers of the array type should be discarded, as they would be for any normal auto deduction.
看来是对的。当你写 auto x = y;
时,你肯定会认为 x
不是顶级的 const
,但我们这里的情况仍然是。我认为目前还没有针对此的核心问题,但应该有。