cv-qualified struct的成员不具有类似的cv限定

Ori*_*ent 6 c++ clang type-traits c++11 c++14

根据这个答案,应该编译以下代码而不会出错:

#include <type_traits>

namespace
{

struct A { int i; };

volatile A a{};
static_assert(std::is_volatile< decltype(a) >{});
static_assert(std::is_volatile< decltype(a.i) >{});

}
Run Code Online (Sandbox Code Playgroud)

但是有一个很难的错误:

main.cpp:10:1: error: static_assert failed
static_assert(std::is_volatile< decltype(a.i) >{});
^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
Run Code Online (Sandbox Code Playgroud)

使用clang 3.6.0的实例.

这是一个铿锵的错误还是我错过了一些实质性的东西?

额外:

#include <type_traits>

namespace
{

struct A { int i; };

const A a{};
static_assert(std::is_const< decltype(a) >{});
static_assert(std::is_const< decltype(a.i) >{});

}
Run Code Online (Sandbox Code Playgroud)

后一个代码片段的行为完全相同.

额外:

static_assert(std::is_volatile< std::remove_pointer_t< decltype(&a.i) > >{});
Run Code Online (Sandbox Code Playgroud)

不会导致错误.

Aar*_*aid 8

这是正确的行为; 目前decltype没有测试你认为它测试的东西.decltype如果要测试volatile-ness,则必须更改.

可以复制值和删除值volatile.但参考必须是不稳定的引用 - 易失性.

int foo() {
    int i = a.i;            // volatile not needed
    volatile int &i = a.i;  // volatile needed
}
Run Code Online (Sandbox Code Playgroud)

decltype处理a.i为右值,不是左值,做什么decltype(默认设置),并做一个"天真"的文本分析和报告的类型A::i写在源代码; 因此,decltype(a.i)int.

()周围的表达decltype(通常是好方法,对于这种问题的)改变其行为,给我们一个左值在适当的时候.因此,decltype(( a.i ))volatile int &.

现在,你可能会认为这is_volatile< volatile int & >::value是真的.但事实并非如此.我们需要在测试volatile-ness 之前删除引用.

static_assert(std::is_volatile< std::remove_reference_t<decltype((a.i))> >{});
Run Code Online (Sandbox Code Playgroud)

最后,你可能会感到惊讶,因为volatile int &根本没有动荡is_volatile.但我想这是因为引用非常类似于指针 - 引用中的'指针'不是易失性的,即使指向的对象是易失性的.无论如何,那是我的理论.const int&也不满足is_const.