The typedef itself isn't the problem. It's perfectly legal to write struct foo; typedef std::pair<foo, foo> bar;
. The problem is with
noexcept(std::declval<type&>() = std::declval<type>());
This requires the compiler to perform overload resolution for operator=
. As part of overload resolution it must look for possible conversions from B&&
to std::pair<A, A>&&
, and that requires instantiating std::pair<A,A>
(§14.7.1 [temp.inst]/p6):
A class template specialization is implicitly instantiated if the
class type is used in a context that requires a completely-defined
object type or if the completeness of the class type might affect the
semantics of the program. [ Note: In particular, if the semantics of
an expression depend on the member or base class lists of a class
template specialization, the class template specialization is
implicitly generated. For instance, deleting a pointer to class type
depends on whether or not the class declares a destructor, and
conversion between pointer to class types depends on the inheritance
relationship between the two classes involved. —end note ]
...and, by §17.6.4.8 [res.on.functions]/p2, this instantiation causes undefined behavior.
Although the compiler is not required to instantiate std::pair<A, A>
in this context since the move assignment operator is an exact match (§14.7.1 [temp.inst]/p7):
If the overload resolution process can determine the correct function
to call without instantiating a class template definition, it is
unspecified whether that instantiation actually takes place.