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)
这是一个铿锵的错误还是我错过了一些实质性的东西?
额外:
#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)
不会导致错误.
这是正确的行为; 目前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.