Search code examples
c++templates

How can the template arguments of a default constructor be different from those of the class in C++?


When reading the implementation of std::pair in gcc source code, I found one of the default constructors as below:

  template<typename _T1, typename _T2>
    struct pair
    : public __pair_base<_T1, _T2>
    {
      typedef _T1 first_type;    ///< The type of the `first` member
      typedef _T2 second_type;   ///< The type of the `second` member

      _T1 first;                 ///< The first member
      _T2 second; 
...
      template <typename _U1 = _T1,
                typename _U2 = _T2,
                typename enable_if<__and_<
                                     __is_implicitly_default_constructible<_U1>,
                                     __is_implicitly_default_constructible<_U2>>
                                   ::value, bool>::type = true>
      constexpr pair()
      : first(), second() { }
...
}

My question is, when using the default ctor to construct an object, it's also the time to instantiate an object of the class as below:

std::pair<int, double> p;

How can _U1 be different from _T1? Thank you guys.


Solution

  • It can't1. By defaulting the constructor template arguments _U1 and _U2 to the class template parameters _T1 and _T2, there is scope for the substitution failure with the third (unnamed) non-type template parameter.

    This is the mechanism by which that overload isn't available when either _T1 or _T2 isn't implicitly default constructable.

    1. Because this is a constructor, there isn't anywhere where _U1 and _U2 can be explicitly specified, so the only source is the default. Normal function templates can have explicit parameters, e.g. std::pair<int, double> pair; pair.operator=<char, float>({'a', 1.0f})