代码之家  ›  专栏  ›  技术社区  ›  Dean Roddey

如何在没有std:whatever[closed]的情况下强制c++移动操作符

  •  -12
  • Dean Roddey  · 技术社区  · 7 年前

    我有一个很大的代码库,已经有一段时间了。我一直在有选择地使用新的语言功能来更新它。我本来打算和移动构造器打交道,但我甚至想不出一个复杂的场景来实现它。我不会把我甚至不能进行单元测试的代码扔进我的代码库。

    而且,我不能使用std:move,因为我根本不使用标准库。我有自己的标准库,还有自己的所有东西(大约一百万行代码),所有东西都隐藏在一个虚拟内核中,不向外界公开任何语言或平台头。

    所以我不能用std::move。希望它不会有什么我做不到的魔法?我想,在面对基类时,处理move构造函数也需要类似的东西(几乎总是这样)。如果它真的做了一些神奇的事情,那就是库泄漏到语言中,那就不好了。

    显然,VisualC++中没有编译设置(在我的例子中是2017)来禁止它从ELIDEN构造函数中删除,这大概是为什么我不能做任何事情来引起它的原因。

    当然,这也提出了一个问题,如果它需要这么多的努力(即使是在非优化模式下)才能实现它,那么它是否毫无用处。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Remy Lebeau    7 年前

    我不能使用std:move,因为我根本不使用标准库…希望它不会有什么我做不到的魔法?

    How does std::move() transfer values into RValues? 以下内容:

    template <typename T>
    typename remove_reference<T>::type&& move(T&& arg)
    {
        return static_cast<typename remove_reference<T>::type&&>(arg);
    }
    

    This answer 详细解释它的工作原理。

    我本来打算和移动构造器打交道,但我甚至想不出一个复杂的场景来实现它。

    调用move构造函数并不困难。例如:

    template< class T > struct my_remove_reference      {typedef T type;};
    template< class T > struct my_remove_reference<T&>  {typedef T type;};
    template< class T > struct my_remove_reference<T&&> {typedef T type;};
    
    template <typename T>
    typename my_remove_reference<T>::type&& my_move(T&& arg)
    {
        return static_cast<typename my_remove_reference<T>::type&&>(arg);
    }
    
    struct S
    {
        int *ptr = nullptr;
    
        S() = default;
        S(int *p) : ptr(p) {}
    };
    
    class MoveTester
    {
    private:
        int *m_ptr = nullptr;
    
    public:
        MoveTester() = default;
        MoveTester(const MoveTester &) = delete;
        MoveTester(MoveTester&& src) : m_ptr(src.m_ptr) { src.m_ptr = nullptr; }
    
        MoveTester(int *ptr) : m_ptr(ptr) {}
        MoveTester(S&& src) : m_ptr(src.ptr) { src.ptr = nullptr; }
    
        MoveTester& operator=(const MoveTester &) = delete;
        MoveTester& operator=(MoveTester&& rhs) { m_ptr = rhs.m_ptr; rhs.m_ptr = nullptr; return *this; }
        MoveTester& operator=(int *rhs) { m_ptr = rhs; return *this; }
        MoveTester& operator=(S&& src) { m_ptr = src.ptr; src.ptr = nullptr; return *this; }
    
        void display(const char *name) const { cout << name << ".m_ptr = " << m_ptr << endl; }
    };
    
    int* int_to_ptr(intptr_t value) { return reinterpret_cast<int*>(value); }
    
    int main()
    {
        MoveTester mt1;
        mt1.display("mt1");
    
        MoveTester mt2 = int_to_ptr(12345);
        mt2.display("mt2");
    
        //MoveTester mt3 = mt2; // compiler error! Copy constructor is deleted
        MoveTester mt3 = my_move(mt2);
        mt2.display("mt2");
        mt3.display("mt3");
    
        MoveTester mt4 = S();
        mt4.display("mt4");
    
        MoveTester mt5 = S(int_to_ptr(67890));
        mt5.display("mt5");
    
        //mt1 = mt5; // compiler error! Copy assignment is deleted
        mt1 = my_move(mt5);
        mt1.display("mt1");
        mt5.display("mt5");
    
        mt1 = int_to_ptr(13579);
        mt1.display("mt1");
    
        mt1 = S();
        mt1.display("mt1");
    
        mt1 = S(int_to_ptr(24680));
        mt1.display("mt1");
    
        return 0;
    }
    

    Live Demo