5

aşağıdaki hatayı alıyorum: Aşağıdaki kod derlenirbelirsiz c 'operatörü =' ++ 11 std :: hamle için aşırı yük ve kopyalayıp takas deyim

[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&&) 

:

#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; 
} 

g++ -std=c++11 main.cpp && ./a.out ile derlenen:

[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 

birisi belirsizlik kullanmanın oluşturduğu neden anlamama yardımcı olabilir misiniz Bu durumda kopyalama ve takas deyim? dönüştürmek için kullanılan kapalı dönüştürme dizileri test ve Test & & çünkü aşırı çözünürlüğü amacıyla

cevap

7

fonksiyonları

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

eşittir, sırasıyla, birbirine eşittir. Birincisi daha iyi değildir, çünkü doğrudan referans bağlaması da bir kimlik dönüşümü olarak kabul edilir.

2 eşit olarak iyi eşleşmelerin belirsizliği ile karşılaştığında, derleyici bir hata verir. Muhtemelen bunu istiyorsanız:

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

+1. Ve problemin çözümü hareket atama operatörü kurtulmak için, kopya-ve-takas bir rvalues ​​_and_ lvalues, bu –

+0

@JonathanWakely tnx, güncellenen kolları. – TemplateRex

+0

@rhalbersma Cevabınız için teşekkürler. Açıkça görüldüğü gibi, örtük dönüşüm dizilerinin neden daha fazla olduğunu anlamak için daha fazla var –