LINUX.ORG.RU

Баг или фича?

 


1

1

#include <vector>

const size_t i = 20;


int main()
{
    //auto p = std::make_pair<void*, size_t>(nullptr, i); // doesn't work
    auto p = std::pair<void*, size_t>(nullptr, i); //works
}

gcc 9.2.0, собираю с -std=c++17

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 1)

Фича

#include <vector>

const size_t i = 20;


int main()
{
    auto p = std::make_pair(nullptr, i); // works OK again
    //auto p = std::pair<void*, size_t>(nullptr, i); //works
}

Обычно в таких случаях надеются на автоматическое выведение аргументов шаблонной функции, но ты указал их явно. И вместо универсальной ссылки во втором аргументе получил std::size_t&&. Отсюда и

cannot bind rvalue reference of type 'long unsigned int&&' to lvalue of type 'const size_t' {aka 'const long unsigned int'}

Makhno
()
Ответ на: комментарий от example_cat

Да ты же поехавший - ты в этом еще и знамение СЖВ увидел.

Makhno
()

Фича, std::make_pair сделано для того, чтоб автоматически определять тип результирующего std::pair (посредством template type deduction).

std::make_pair использует так называемую universal (aka forwarding) reference: T&&. Такая ссылка «схлопывается» по особым правилам: https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers

Специализируя std::make_pair ты нарушаешь его семантику. Т.е. вместо forwarding reference твоя специализация принимает rvalue reference.

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 1)

да, всё норм.

Просто прочти ошибку компилятора:

невозможно преобразовать аргумент 2 из "const size_t" в "size_t &&"
fsb4000 ★★★★★
()
Ответ на: комментарий от fsb4000

Ок. Хрен бы знал, правда, где я утверждал обратное.

Makhno
()
Ответ на: Фича от Makhno

auto p = std::make_pair(nullptr, i); // works OK again

Очевидно, что это не то что я хочу. Я пример утрировал. Просто показалось забавным такое поведение, оно не то чтобы очевидно=)

Dudraug ★★★★★
() автор топика
Ответ на: комментарий от KennyMinigun

Забавно, спасибо. Век живи, век учись. Просто уже после умных указательей привычка использовать make_blabla как более выскоуровневый инструмент, чем конструктор напрямую. Но в целом здесь мне make_pair и не нужен, конструктор подходит. Топик создал из любопытства.

Dudraug ★★★★★
() автор топика
Ответ на: комментарий от Dudraug

make_blabla как более выскоуровневый инструмент, чем конструктор напрямую.

В С++17, кстати, появились template deduction guidelines, так что теперь в большинстве случаев std::make_pair не нужен (т.е. можно писать std::pair{first, second}).

KennyMinigun ★★★★★
()
Ответ на: комментарий от KennyMinigun

Это я знаю=) Но здесь мне как раз это не нужно, я не просто так пытался явно make_pair специализировать. Ну да ладно=)

Dudraug ★★★★★
() автор топика
Ответ на: комментарий от KennyMinigun

Похоже, твой мозг схлопнулся

Такая ссылка «схлопывается» по особым правилам

Все ссылки «схлопываются» по одинаковым правилам.

Для forwarding ссылок особое правило вывода типа: для lvalue аргументов используется не тип аргумента A, а A&:

https://timsong-cpp.github.io/cppwp/n4659/temp.deduct.call#3

If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.