Нарушение изменений в С++ 11 с make_pair (_Ty1 && _Val1, const _Ty2 & _Val2)

Рассмотрим следующую программу на С++

#include<map>
#include<iostream>
int main() {
    int a = 5, b = 7;
    auto pair = std::make_pair<int, int>(a,b);
    return 0;
    }

Использование VC11, а также в gcc-4.7.2 завершается с ошибкой с различными ошибками, хотя похоже, что это связано, и сообщение об ошибке VC11 более значимо

You cannot bind an lvalue to an rvalue   

То, что я понимаю из этого отказа,

  • VC11, и я полагаю, что gcc-4.7.2 имеет только одну реализацию std:: make_pair make_pair(_Ty1&& _Val1, const _Ty2& _Val2), которая может принимать только ссылку rvalue. Пример предыдущей версии VС++ VC10 имел две версии, один для принятия значения lvalue, а другой - для ссылки rvalue
  • Ссылка Rvalue не может использоваться для инициализации ссылки не const, т.е. int & a = b * 5 является недопустимым.
  • Я мог бы использовать std::move для преобразования ссылки lvalue в rvalue, и вызов будет успешным.
  • Поскольку std::make_pair принимает два разных типа для каждого из параметров, разрешение аргумента шаблона во всех возможных случаях может разрешить тип параметра, и явно не указывать тип не требуется.

Этот сценарий кажется тривиальным, и несовместимость можно легко решить, удалив явную спецификацию типа и сделав определение как

auto pair = std::make_pair(a,b);
  • Теперь, мой вопрос: каков главный фактор для удаления реализации lvalue из библиотеки?
  • Возможно ли узнать любые другие библиотечные функции, которые были изменены аналогичным образом?
  • Как справиться с этими ситуациями, когда мне нужно настроить несколько компиляторов, таких как g++, CC, aCC, XL С++, где либо компиляторы не были обновлены, либо компилятор не поддерживает ссылку rvalue и не перемещает семантику.

Ответ 1

std::make_pair существует с единственной целью использования вывода типа, чтобы избежать ввода имен типов. Вот почему есть только одна перегрузка (и она должна принимать две универсальные ссылки, а не одну универсальную ссылку и ссылку lvalue на const, поскольку кажется, что VC думает).

template <class T1, class T2>
constexpr pair<V1, V2> make_pair(T1&& x, T2&& y);

Если вы хотите явно вводить типы, вы можете просто использовать конструктор пары. Это еще короче...

auto pair = std::pair<int, int>(a,b);

Ответ 2

Когда вы выполняете std::make_pair<int, int>, вы вынуждаете аргументы шаблона T1 и T2 обеим выводам как int. Это дает вам функцию std::pair<int,int> make_pair(int&&, int&&). Теперь эти аргументы могут принимать только значения r потому, что они являются ссылками rvalue.

Однако, когда типы T1 и T2 выводятся методом вывода типа шаблона, они действуют как "универсальные ссылки". То есть, если они получают аргумент lvalue, они будут ссылками lvalue, и если они получат аргумент rvalue, они будут ссылками rvalue. Это дает возможность make_pair совершать совершенную переадресацию.

Итак, точка не содержит явно аргументов типа шаблона. Вся точка make_pair заключается в том, что она выводит сами типы. Если вы назовете типы, он больше не сможет совершить совершенную переадресацию и будет терпеть неудачу для аргументов lvalue.