cv-qualified struct 的成员不是类似的 cv-qualified
cv-qualified struct's member is not similarly cv-qualified
根据这个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.
这是一个 clang bug 还是我遗漏了一些重要的东西?
附加:
#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) > >{});
不会导致错误。
这是正确的行为;当前 decltype
并没有测试您认为它测试的内容。如果你想测试 volatile
-ness,你必须改变你的 decltype
。
可以复制一个值并删除 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
默认执行的操作,并且正在执行"naive" 文本分析和报告 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))> >{});
最后,根据 is_volatile
,volatile int &
不是易变的,您可能会感到惊讶。但我想这是因为引用真的非常像指针——引用中的 'pointer' 不是易变的,即使指向的对象是易变的。无论如何,这就是我的理论。 const int&
也不满足is_const
.
根据这个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.
这是一个 clang bug 还是我遗漏了一些重要的东西?
附加:
#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) > >{});
不会导致错误。
这是正确的行为;当前 decltype
并没有测试您认为它测试的内容。如果你想测试 volatile
-ness,你必须改变你的 decltype
。
可以复制一个值并删除 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
默认执行的操作,并且正在执行"naive" 文本分析和报告 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))> >{});
最后,根据 is_volatile
,volatile int &
不是易变的,您可能会感到惊讶。但我想这是因为引用真的非常像指针——引用中的 'pointer' 不是易变的,即使指向的对象是易变的。无论如何,这就是我的理论。 const int&
也不满足is_const
.