【发布时间】:2016-04-27 14:28:51
【问题描述】:
我创建了一个简单的类型特征来删除右值引用:
template <typename T>
struct remove_rvalue_reference { using type = T; };
template <typename T>
struct remove_rvalue_reference<T&&> { using type = T; };
template <typename T>
using remove_rvalue_reference_t =
typename remove_rvalue_reference<T>::type;
我用它来实现一个copy_if_rvalue(x) 函数,它的返回类型取决于传递的参数:
template <typename T>
constexpr auto copy_if_rvalue(T && x)
-> remove_rvalue_reference_t<decltype(std::forward<decltype(x)>(x))>
{
return std::forward<decltype(x)>(x);
}
为了确保函数返回正确的类型,我编写了一些简单的静态断言:
// literal
static_assert(std::is_same<
decltype(copy_if_rvalue(0)), int
>{});
// lvalue
int lv = 10;
static_assert(std::is_same<
decltype(copy_if_rvalue(lv)), int&
>{});
// const lvalue
const int clv = 10;
static_assert(std::is_same<
decltype(copy_if_rvalue(clv)), const int&
>{});
// rvalue
int rv = 10;
static_assert(std::is_same<
decltype(copy_if_rvalue(std::move(rv))), int
>{});
// volatile lvalue
volatile int vlv = 10;
static_assert(std::is_same<
decltype(copy_if_rvalue(vlv)), volatile int&
>{});
// const lvalue
volatile const int vclv = 10;
static_assert(std::is_same<
decltype(copy_if_rvalue(vclv)), volatile const int&
以上所有静态断言都编译成功。但是,当尝试 std::move volatile int 变量时,会发生意外情况:
// volatile rvalue
volatile int vrv = 10;
// (0) fails:
static_assert(std::is_same<
decltype(copy_if_rvalue(std::move(vrv))), volatile int
>{});
// (1) unexpectedly passes:
static_assert(std::is_same<
decltype(copy_if_rvalue(std::move(vrv))), int
>{});
// (2) unexpectedly passes:
static_assert(std::is_same<
remove_rvalue_reference_t<decltype(std::forward<decltype(vrv)>(std::move(vrv)))>,
volatile int
>{});
断言 (0) 失败 - volatile 不会传播,如断言 (1) 所示。
但是,断言(2)通过了,即使我认为它应该等同于断言(0),因为copy_if_rvalue的返回类型与(2)的第一种类型完全相同:
// (from assertion (2))
remove_rvalue_reference_t<decltype(std::forward<decltype(vrv)>(std::move(vrv)))>
// ...should be equivalent to...
// (from copy_if_rvalue)
-> remove_rvalue_reference_t<decltype(std::forward<decltype(x)>(x))>
似乎volatile 仅在使用std::move 时才传播,并且仅通过copy_if_rvalue 模板函数传播。
这是怎么回事?
【问题讨论】:
-
简体 example : (
const int foo();decltype(foo())是int)。 -
见stackoverflow.com/a/13155026/34509。这不仅适用于
const,也适用于volatile。
标签: c++ language-lawyer c++14 decltype trailing-return-type