根据这个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.
这是一个铿锵的错误还是我错过了一些实质性的东西?
其他
#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) > >{});
不会导致错误。
答案 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
}
decltype
是将执行a.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
。