Обнаружил, что не понимаю, почему вызывается шаблонный конструктор перемещения, вместо нешаблонного в таком коде:
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.
вообще, очень сложно отвечать, потому как код разбросан по трем сниппетам. невозможно на них ссылаться.
лучше, приведи один пример, с одним конкретным вопросом.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Здравствуйте, PM, Вы писали:
PM>Здравствуйте, niXman, Вы писали:
X>>тут Y(T&& y), насколько я понимаю, y является универсальной ссылкой, а не r-value ссылкой.
PM>Допустим, но ведь по правилам перегрузки Y(Y&&) должно быть более подходящей кандидатурой, чем Y(T&& y), или я что-то упускаю?
Упускаешь правила работы универсальных ссылок.
Коротко: если ты ей даешь на вход rvalue — она даст тебе rvalue reference. Если lvalue — даст lvalue reference.
Соответственно в вызове Y y2 = y1; универсальная ссылка превращается в обычную ссылку Y(Y&), что является более подходящим, чем Y(Y&&).
Здравствуйте, jazzer, Вы писали:
X>>>тут Y(T&& y), насколько я понимаю, y является универсальной ссылкой, а не r-value ссылкой.
PM>>Допустим, но ведь по правилам перегрузки Y(Y&&) должно быть более подходящей кандидатурой, чем Y(T&& y), или я что-то упускаю?
J>Упускаешь правила работы универсальных ссылок. J>Коротко: если ты ей даешь на вход rvalue — она даст тебе rvalue reference. Если lvalue — даст lvalue reference. J>Соответственно в вызове Y y2 = y1; универсальная ссылка превращается в обычную ссылку Y(Y&), что является более подходящим, чем Y(Y&&).
Да, точно, нужен ведь явный move чтобы получить rvalue reference из именованного объекта. Спасибо, стало понятнее.
Какое новое поле граблей добавилось в C++11 с появлением новых типов ссылок, особенно если еще вспомнить про правила default/delete для конструкторов и операторов присваивания
Re[5]: Вопрос про конструктор перемещения [offtop]
Здравствуйте, PM, Вы писали:
PM>Какое новое поле граблей добавилось в C++11 с появлением новых типов ссылок, особенно если еще вспомнить про правила default/delete для конструкторов и операторов присваивания
Ничего, зато С++ программисты по прежнему будут много зарабатывать. Ибо опять увеличился порог вхождения.