5

Sto ottenendo il seguente errore:sovraccarico ambiguo per 'operatore =' con C++ 11 std :: spostare e copiare e scambiare linguaggio

[matt ~] g++ -std=c++11 main.cpp -DCOPY_AND_SWAP && ./a.out 
main.cpp: In function ‘int main(int, const char* const*)’: 
main.cpp:101:24: error: ambiguous overload for ‘operator=’ in ‘move = std::move<Test&>((* & copy))’ 
main.cpp:101:24: note: candidates are: 
main.cpp:39:7: note: Test& Test::operator=(Test) 
main.cpp:52:7: note: Test& Test::operator=(Test&&) 

Quando il seguente codice viene compilato:

#include <iostream> 
#include <unordered_map> 
class Test final { 
public: 
    typedef std::unordered_map<std::string, std::string> Map; 
public: 
    Test(); 
    explicit Test(Map&& map); 
    ~Test(); 
    Test(const Test& other); 
    Test(Test&& test); 
#ifdef COPY_AND_SWAP 
    Test& operator=(Test other); 
#else 
    Test& operator=(const Test& other); 
#endif 
    Test& operator=(Test&& other); 
    size_t Size() const noexcept; 
    friend void swap(Test& lhs, Test& rhs); 
private: 
    friend std::ostream& operator<<(std::ostream& stream, const Test& test); 
private: 
    Map map_; 
}; 
Test::Test() : map_() { 
    std::cerr << "Default constructor called" << std::endl; 
}; 
Test::Test(const Test& other) : map_(other.map_) { 
    std::cerr << "Copy constructor called" << std::endl; 
}; 
Test::Test(Test&& other) : map_(std::move(other.map_)) { 
    std::cerr << "Move constructor called" << std::endl; 
}; 
Test::Test(Map&& map) : map_(std::move(map)) { 
    std::cerr << "Map constructor called" << std::endl; 
}; 
Test::~Test() {}; 
#ifdef COPY_AND_SWAP 
Test& Test::operator=(Test other) { 
    std::cerr << "Copy and swap assignment called" << std::endl; 
    using std::swap; 
    swap(this->map_, other.map_); 
    return *this; 
} 
#else 
Test& Test::operator=(const Test& other) { 
    std::cerr << "Copy assignment called" << std::endl; 
    this->map_ = other.map_; 
    return *this; 
} 
#endif 
Test& Test::operator=(Test&& other) { 
    std::cerr << "Move assignment called" << std::endl; 
    this->map_ = other.map_; 
    other.map_.clear(); 
    return *this; 
} 
size_t Test::Size() const noexcept { 
    return map_.size(); 
} 
void swap(Test& lhs, Test& rhs) { 
    using std::swap; 
    swap(lhs.map_, rhs.map_); 
} 
std::ostream& operator<<(std::ostream& stream, const Test& test) { 
    return stream << test.map_.size(); 
} 
int main (const int argc, const char * const * const argv) { 
    using std::swap; 
    Test::Map map { 
    {"some", "dummy"}, 
    {"data", "to"}, 
    {"fill", "up"}, 
    {"the", "map"} 
    }; 
    std::cout << " map size(): " << map.size() << std::endl; 
    std::cout << "Constructing" << std::endl; 
    Test test(std::move(map)); 
    std::cout << " map.size(): " << map.size() << std::endl; 
    std::cout << "test.Size(): " << test.Size() << std::endl; 
    std::cout << "Copy construction" << std::endl; 
    Test copy(test); 
    std::cout << "copy.Size(): " << copy.Size() << std::endl; 
    std::cout << "Move construction" << std::endl; 
    Test move(std::move(copy)); 
    std::cout << "move.Size(): " << move.Size() << std::endl; 
    std::cout << "copy.Size(): " << copy.Size() << std::endl; 
    std::cout << "Swapping" << std::endl; 
    swap(move, copy); 
    std::cout << "move.Size(): " << move.Size() << std::endl; 
    std::cout << "copy.Size(): " << copy.Size() << std::endl; 
    std::cout << "Swapping back" << std::endl; 
    swap(move, copy); 
    std::cout << "move.Size(): " << move.Size() << std::endl; 
    std::cout << "copy.Size(): " << copy.Size() << std::endl; 
    std::cout << "Copy assignment" << std::endl; 
    copy = test; 
    std::cout << "test.Size(): " << test.Size() << std::endl; 
    std::cout << "copy.Size(): " << copy.Size() << std::endl; 
    std::cout << "Move assignment" << std::endl; 
    move = std::move(copy); 
    std::cout << "move.Size(): " << move.Size() << std::endl; 
    std::cout << "copy.Size(): " << copy.Size() << std::endl; 
return 0; 
} 

quando si compila con g++ -std=c++11 main.cpp && ./a.out:

[matt ~] g++ -std=c++11 main.cpp && ./a.out 
map size(): 4 
Constructing 
Map constructor called 
map.size(): 0 
test.Size(): 4 
Copy construction 
Copy constructor called 
copy.Size(): 4 
Move construction 
Move constructor called 
move.Size(): 4 
copy.Size(): 0 
Swapping 
move.Size(): 0 
copy.Size(): 4 
Swapping back 
move.Size(): 4 
copy.Size(): 0 
Copy assignment 
Copy assignment called 
test.Size(): 4 
copy.Size(): 4 
Move assignment 
Move assignment called 
move.Size(): 4 
copy.Size(): 0 

qualcuno potrebbe aiutarmi a capire il motivo per cui l'ambiguità si verifica quando si utilizza il copiare e scambiare l'idioma in questo caso?

risposta

7

per scopi risoluzione sovraccarico funzioni

Test& operator=(Test other); 
Test& operator=(Test&& other); 

sono uguali, poiché le sequenze di conversione implicite utilizzati per convertire in prova e prova & &, rispettivamente, sono uguali. Il primo non è migliore, perché il legame diretto di riferimento è anche considerato una conversione di identità.

Di fronte all'ambiguità di 2 corrispondenze ugualmente valide, il compilatore restituisce un errore. Probabilmente vuoi questo:

#ifdef COPY_AND_SWAP 
    Test& operator=(Test other); 
#else 
    Test& operator=(const Test& other); 
    Test& operator=(Test&& other); 
#endif 
+2

+1. E la soluzione al problema è di eliminare l'operatore di assegnazione del movimento, lo strumento copia-e-swap gestisce rvalues ​​_and_ lvalues, questo è il punto –

+0

@JonathanWakely tnx, aggiornato. – TemplateRex

+0

@rhalbersma Grazie per la risposta. Ovviamente ho più da capire sul motivo per cui le sequenze di conversione implicite sono le stesse comprendendo i rvalues ​​di più –

Problemi correlati