c++ - 对 const c 数组拷贝的结构化绑定(bind)应该是 const 吗?

标签 c++ language-lawyer c++17 structured-bindings

考虑一下这段代码(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?)
    }

结构化绑定(bind)const c-array的拷贝由Clang声明constnon-const 由 GCC 提供。

GCC 对 c 数组的行为与观察到的聚合或类元组类型的行为一致。

另一方面,根据我对标准的阅读,我认为 Clang 遵循所写的内容。在 [dcl.struct.bind]/1 e 具有 cv A 类型,其中 A 是初始化表达式的类型,而 cv 是结构化绑定(bind)声明的 cv 限定符。并且初始化表达式 ar 的类型对应于 [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]。因此,按照措辞,每个绑定(bind)都引用元素类型——即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,但这里我们有一种情况它仍然是。我认为目前还没有针对此问题的核心问题,但应该存在。

关于c++ - 对 const c 数组拷贝的结构化绑定(bind)应该是 const 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53726135/

相关文章:

c++ - gcc 插件 c c++ 查找全局非静态变量

c++ - Obj-C-C++ 中的 OpenCV goodFeaturesToTrack

c++ - std::string 实现是否符合 's.c_str() + s.size()' 不一定与 '&s[s.size()]' 相同?

c - 可以为 scanf ("%x"传递 int 的地址吗,...)?

c++ - 为什么在访问空的 std::optional 时没有抛出或 sigsegv?

c++ - 使用 std c++11 中的 Boost Test Unit 进行编译

c++ - 指向链表中的第一个对象,类内还是类外?

c++ - 不同数字类型的相同比较

c++ - 不同翻译单元中不可重载的非内联函数定义

c++ - GCM 中的 Crypto++ AES 正在生成类似的密文