Исключая конструкторы std:: pair, которые используют явное построение

Следуя этому ответу, кажется, что эти конструкторы:

template<class U, class V> pair(pair<U, V>&& p); 
template<class U, class V> pair(const pair<U, V>& p);

запрещается участвовать в разрешении перегрузки, когда требуется явное преобразование.

Из С++ 11 (§20.3.2, n3290):

Примечание. Этот конструктор не должен участвовать в разрешении перегрузки, если U неявно конвертируется в first_type, а V неявно конвертируется в second_type.

Предложен интересный метод обхода SFINAE, но это отступает от текста стандарта.

Как совместимая реализация может исключить это из-за разрешения перегрузки, за исключением некоторой специальной внутренней магии компилятора? То есть может ли реализация сделать это, и я могу дублировать ее для моего собственного типа, возможно? Похоже, что это не соответствует этому! Это похмелье от удаления понятий из С++ 11?

Я действительно задавался вопросом об использовании частного конструктора для выполнения части SFINAE и делегирования из конструктора public, но он не похож на то, что делегирование конструктора участвует в SFINAE таким образом, чтобы сделать эту работу.

Ответ 1

но это отступление от текста стандарта

Реализации разрешено добавлять аргументы по умолчанию для любой функции не виртуальной библиотеки. Это, похоже, позволяет именно такие трюки SFINAE.

Ответ 2

Мне не хватало двух частей информации:

  • gcc использует это:

    template<class _U1, class _U2, class = typename
                   std::enable_if<std::is_convertible<_U1, _T1>::value
                                  && std::is_convertible<_U2, _T2>::value>::type>
            pair(_U1&& __x, _U2&& __y)
            : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
    

    Кажется, что трюк по умолчанию используется для анонимного параметра шаблона class. Я не видел этого раньше, и эта реализация не использовала это.

  • Я пропустил, что gcc действительно реализовал это.