два конструктора пары почти одинаковы, почему бы не сгенерировать ошибку сборки? - PullRequest
0 голосов
/ 06 июля 2018

В реализации пары следующие два конструктора отличаются только префиксом: явный. функция шаблона с двумя членами почти одинакова.

template<class _Other1,
        class _Other2,
        enable_if_t<conjunction_v<
            is_constructible<_Ty1, _Other1>,
            is_constructible<_Ty2, _Other2>,
            is_convertible<_Other1, _Ty1>,
            is_convertible<_Other2, _Ty2>
        >, int> = 0>
        constexpr pair(_Other1&& _Val1, _Other2&& _Val2)
            _NOEXCEPT_COND(is_nothrow_constructible_v<_Ty1, _Other1>
                && is_nothrow_constructible_v<_Ty2, _Other2>)
        : first(_STD forward<_Other1>(_Val1)),
                second(_STD forward<_Other2>(_Val2))
        {   // construct from moved values
        }

    template<class _Other1,
        class _Other2,
        enable_if_t<conjunction_v<
            is_constructible<_Ty1, _Other1>,
            is_constructible<_Ty2, _Other2>,
            negation<conjunction<
                is_convertible<_Other1, _Ty1>,
                is_convertible<_Other2, _Ty2>>>
        >, int> = 0>
        constexpr explicit pair(_Other1&& _Val1, _Other2&& _Val2)
            _NOEXCEPT_COND(is_nothrow_constructible_v<_Ty1, _Other1>
                && is_nothrow_constructible_v<_Ty2, _Other2>)
        : first(_STD forward<_Other1>(_Val1)),
                second(_STD forward<_Other2>(_Val2))
        {   // construct from moved values
        }

Но когда я напишу свой тестовый пример следующим образом:

class A
{
public:
    template<typename T1,typename T2>
    A(T1 a,T2 b){}

    template<typename T1,typename T2>
    explicit A(T1 a,T2 b){}
};

Ошибка сборки выглядит так:

Error   C2535   'A::A(T1,T2)': member function already defined

Так почему же результат отличается?

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Разница не только в использовании explicit, но и в аргументах шаблона есть другое условие для enable_if_t:

//     Constructor 1                            Constructor 2
enable_if_t<conjunction_v<               enable_if_t<conjunction_v<
  is_constructible<_Ty1, _Other1>,         is_constructible<_Ty1, _Other1>,
  is_constructible<_Ty2, _Other2>,         is_constructible<_Ty2, _Other2>,
  is_convertible<_Other1, _Ty1>,           negation<conjunction<
  is_convertible<_Other2, _Ty2>              is_convertible<_Other1, _Ty1>,
                                             is_convertible<_Other2, _Ty2>>>

Первый конструктор вызывается, если выполняются все четыре условия (_Ty1/2 может быть построено из _Other1/2 и _Other1/2 может быть преобразовано в _Ty1/2). Второе вызывается, только если последние два условия ложны.

explicit сам по себе не влияет на разрешение перегрузки, это просто означает, что конструктор может использоваться только в контексте прямой инициализации.

0 голосов
/ 06 июля 2018

Класс ниже не использует шаблон выше.

Ошибка вызвана тем, что вы описываете один и тот же конструктор дважды.

explicit - это всего лишь ограничение того, как конструктор может быть вызван, а не изменение подписи, которое допускает перегрузку.

...