C++ 不允许转换为右值引用

C++ disallow cast to rvalue reference

与已经 std::move 的变量一样,之后使用它们是不安全的。

由于我编写了鼓励用户在各种场合应用 std::move 的代码,因此我想避免以错误的方式使用它,至少在一些关键的地方(以便选择性地说 "protect against Machiavelli").

因此,std::move 的以下重载是否是一个有效的方法?还是您不鼓励使用它?

struct A
{
     void do_something() const { /* ... whatever ... */ }
};

namespace std
{
    auto move(A& t) noexcept = delete;
    auto move(A const& t) noexcept = delete;
    //possibly the same for volatile qualifier

    //possibly also specialize static_cast<A const&>, static_cast<A&>, etc.
}

// possibly set up another function "my_private_move"
// which I can use exclusively where it is appropriate.

int main()
{
    A a;
    // auto a_moved = std::move(a);      //disallow move of lvalue ref
    a.do_something();                    //otherwise this could be problematic

    A(A{});                             //direct initialization via move constructor is ok
    auto x2 = A{};                      
}

根据 [namespace.std]:

,您的代码表现出未定义的行为

The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified. A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.

您的用例不属于 "otherwise specified" 范畴。除了未定义之外,它的价值值得怀疑......你不允许这样做:

A a; 
f(std::move(a)); 
// just don't use a here

尽管这可能比 f(a) 有性能改进。但是用户仍然可以显式地编写转换来实现相同的结果:

f(static_cast<A&&>(a)); // slightly more verbose move

As always with variables which have been std::move'd, it is unsafe to use them afterwards

这根本不是真的。使用已经搬走的东西是绝对安全的。在被标准移动后,有很多地方必须使用它们,例如std::swap甚至只是破坏局部变量。

不能做的是假设他们有任何特定有效状态。但他们必须有一些有效状态。如果您正在创作 A 并且它不遵守这些规则,那么 A 已经损坏并且应该被修复,而不是用创可贴来解决这个问题。

A a;
auto a_moved = std::move(a); //disallow move of lvalue ref
a.do_something(); //otherwise this could be problematic

std::move() 的要点是取左值,return 取右值,以便可以调用移动构造函数或移动赋值。因此,要么删除移动构造函数和移动赋值,要么您的用户只需要知道他们在做什么。这是关于 std::move() http://en.cppreference.com/w/cpp/utility/move

的一些信息