gpt4 book ai didi

c++ - 组合 std::forward、std::move 和 volatile 时的意外返回类型

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:37:03 25 4
gpt4 key购买 nike

代码 on gcc.godbolt.org .

我创建了一个简单的类型特征来删除右值引用:

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 模板函数传播。

这是怎么回事?

最佳答案

没有 cv 限定的标量纯右值。 [expr]/6 :

If a prvalue initially has the type “cv T”, where T is a cv-unqualified non-class, non-array type, the type of the expression is adjusted to T prior to any further analysis.

即同样的规则给出

int const f();
f() // <=

type int 也适用于此。如果您尝试使用某种类类型而不是 int(例如 std::string),您将获得预期的类型。

关于c++ - 组合 std::forward、std::move 和 volatile 时的意外返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36892827/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com