VC2015: шаблонный перемещающий конструктор вместо шаблонного конструктора копий
От: Анатолий Широков СССР  
Дата: 18.03.16 10:04
Оценка: 1 (1)
Собственно, вопроса особенного нет, просто информация, хотя если у кого-то есть версия, почему это происходит welcome.

VC2015 спокойно предпочитает для lvalue вызов шаблонного перемещающего конструктора rvalue (**), игнорируя перегрузку шаблонного копирующего конструктора c const lvalue (*)

  class foo {
  public:
    foo() {}
    ~foo() {}
    foo(const foo&) {}
    foo(foo&&) {}
    foo& operator=(const foo&) { return *this; }
    foo& operator=(foo&&) { return *this; }
    template<typename T> explicit foo(const T& x) {} // (*)
    template<typename T> explicit foo(T&& x) {}  // (**)
  };
  TEST(FooTest, VC2015) {
    std::string s("hello");
    foo f(s);  // ok for VC2015, template<typename T> explicit foo(T&& x) will be called
  }


Проблема решается путем добавления третьей перегрузки для lvalue:

    template<typename T> explicit foo(T& x) {} // (*)



Между тем, нешаблонные версии конструкторов работают как и ожидалось (компилятор отлавливает ошибку):

  class boo {
  public:
    boo() {}
    ~boo() {}
    boo(const boo&) {}
    boo(boo&&) {}
    boo& operator=(const boo&) { return *this; }
    boo& operator=(boo&&) { return *this; }
    // explicit boo(const std::string& x) {}
    explicit boo(std::string&& x) {} 
  };
  TEST(BooTest, VC2015) {
    std::string s("hello");
    boo f(s);  // error C2664: '`anonymous-namespace'::boo::boo(const `anonymous-namespace'::boo &)': cannot convert argument 1 from 'std::string' to 'std::string &&'
  }
vs2015 vc2015
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.