cv-qualified struct的成员不具有类似的cv资格

时间:2015-07-31 09:05:46

标签: c++ c++11 clang c++14 typetraits

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

#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) >{});

}

但是有一个很难的错误:

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

Live example with 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) >{});

}

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

其他

static_assert(std::is_volatile< std::remove_pointer_t< decltype(&a.i) > >{});

不会导致错误。

1 个答案:

答案 0 :(得分:8)

这是正确的行为;当前decltype不会测试您认为测试的内容。如果您要测试decltype - nss。

,则必须更改volatile

可以复制一个值并删除volatile - ness。但引用必须是 volatile reference-to-volatile。

int foo() {
    int i = a.i;            // volatile not needed
    volatile int &i = a.i;  // volatile needed
}

decltypea.i视为右值,而不是左值,执行decltype默认执行的操作并且正在执行&#34;天真& #34;文本分析并报告源代码中所写的A::i类型;因此,decltype(a.i)int

()放在decltype中的表达式周围会改变其行为(对于这类问题通常会以良好的方式),在适当的时候给我们一个左值。因此,decltype(( a.i ))volatile int &

现在,您可能希望is_volatile< volatile int & >::value成立。但事实并非如此。我们需要在测试volatile之前删除引用。

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

最后,根据volatile int &,您可能会感到惊讶is_volatile不易变。但我猜它是因为引用非常像指针 - 而指针&#39;即使指向的对象是易失性的,引用内部也不易变。无论如何,那是我的理论。 const int&也不满足is_const