Назначение перемещения несовместимо со стандартным копированием и обменом

Тестирование новой семантики Move.

Я только что спросил о проблемах, которые у меня были с конструктором Move. Но, как выясняется в комментариях, проблема в том, что "Перемещение Назначение " оператор иСтандартное задание " оператор столкновения при использовании стандартаКопировать и поменять » идиома.

Это класс, который я использую:

#include 
#include 

class String
{
    int         len;
    char*       data;

    public:
        // Default constructor
        // In Terms of C-String constructor
        String()
            : String("")
        {}

        // Normal constructor that takes a C-String
        String(char const* cString)
            : len(strlen(cString))
            , data(new char[len+1]()) // Allocate and zero memory
        {
            memcpy(data, cString, len);
        }

        // Standard Rule of three
        String(String const& cpy)
            : len(cpy.len)
            , data(new char[len+1]())
        {
            memcpy(data, cpy.data, len);
        }
        String& operator=(String rhs)
        {
            rhs.swap(*this);
            return *this;
        }
        ~String()
        {
            delete [] data;
        }
        // Standard Swap to facilitate rule of three
        void swap(String& other) throw ()
        {
            std::swap(len,  other.len);
            std::swap(data, other.data);
        }

        // New Stuff
        // Move Operators
        String(String&& rhs) throw()
            : len(0)
            , data(null)
        {
            rhs.swap(*this);
        }
        String& operator=(String&& rhs) throw()
        {
            rhs.swap(*this);
            return *this;
        }
};

Думаю, довольно болотный стандарт.

Затем я проверил мой код следующим образом:

int main()
{
    String  a("Hi");
    a   = String("Test Move Assignment");
}

Здесь назначениеa следует использоватьПеремещение Назначение " оператор. Но есть столкновение с "Стандартное задание " оператор (который написан как ваш стандартный копирования и обмена).

> g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/include/c++/4.2.1
Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
Target: x86_64-apple-darwin13.0.0
Thread model: posix

> g++ -std=c++11 String.cpp
String.cpp:64:9: error: use of overloaded operator '=' is ambiguous (with operand types 'String' and 'String')
    a   = String("Test Move Assignment");
    ~   ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
String.cpp:32:17: note: candidate function
        String& operator=(String rhs)
                ^
String.cpp:54:17: note: candidate function
        String& operator=(String&& rhs)
                ^

Теперь я могу это исправить, изменивСтандартное задание " Оператор:

    String& operator=(String const& rhs)
    {
        String copy(rhs);
        copy.swap(*this);
        return *this;
    }

Но это не хорошо, так как это портит компиляторспособность оптимизировать копирование и обмен. Смотрите Что такое идиома копирования и обмена?Вот а такжеВот

Я что-то упускаю не так очевидно?