Вопрос про конструктор перемещения
От: PM  
Дата: 23.02.15 10:01
Оценка:
Всем привет,

Обнаружил, что не понимаю, почему вызывается шаблонный конструктор перемещения, вместо нешаблонного в таком коде:
struct Y
{
    Y() { std::cout << "default ctor\n"; }

    Y(Y&&) { std::cout << "move ctor\n"; }
    template<typename T>
    Y(T&& y) { std::cout << "move<T> ctor\n"; }
};

int main()
{
    Y y1;
    Y y2 = y1;  // ожидаю move ctor, получаю move<T> ctor
    Y y3 = 22;  // здесь как и должно быть, move<T> ctor
}


Это как-то неожиданно, так как конструкторы копирования работают ожидаемо:
struct Y
{
    Y() { std::cout << "default ctor\n"; }

    Y(Y const&) { std::cout << "copy ctor\n"; }
    template<typename T>
    Y(T const& y) { std::cout << "copy<T> ctor\n"; }
};

int main()
{
    Y y1;
    Y y2 = y1;  // copy ctor
    Y y3 = 22;  // copy<T> ctor
}


Беглый просмотр разделов "Copy constructors", "Move constructors" и "Memeber templates" на cppreference.com ясности не добавил. В итоге проблему обошел с помощью enable_if, но непонимание причины осталось. Есть только предположение, что тут какие-то тонкости copy elision.

Решение с enable_if:
struct Y
{
    Y() { std::cout << "default ctor\n"; }

    Y(const Y&) { std::cout << "copy ctor\n"; }
    template<typename T>
    Y(T const&) { std::cout << "copy<T> ctor\n"; }

    Y(Y&&) { std::cout << "move ctor\n"; }
    template<typename T,
        typename = typename std::enable_if<!std::is_same<Y, typename std::decay<T>::type>::value>::type>
    Y(T&& y) { std::cout << "move<T> ctor\n"; }
};

int main()
{
    Y y1;
    Y y2 = y1;              // copy ctor
    Y y3 = std::move(y1);   // move ctor
    Y y4 = true;            // move<T> ctor
}


Код: http://coliru.stacked-crooked.com/a/57c4420a80d33963
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.