This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 116a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-12-19


2794. Uniqueness of lambdas in alias templates

Section: 13.7.8  [temp.alias]     Status: open     Submitter: Ilya Biryukov     Date: 2023-04-19

Consider:

  template<class T> using A = decltype([]{});

  static_assert(std::same_as<A<int>, A<int>>);

There is implementation divergence: GCC and MSVC accept, clang rejects. A similar question arises if token-identical alias templates appear in different translation units:

  // appearing in multiple translation units
  template<typename T> using A = decltype([]{});
  inline A<int> f() { return {}; }

An alias template is a templated entity per 13.1 [temp.pre] paragraph 8.1, thus it is a definable item (6.3 [basic.def.odr] paragraph 1.5) and thus there is effectively only a single definition of it (6.3 [basic.def.odr] paragraph 15).

However, that reasoning does not address the question whether A<int> denotes the same type when it appears repeatedly in the same translation unit. Consider 13.7.7.2 [temp.over.link] paragraph 5:

Two lambda-expressions are never considered equivalent.

and 13.7.8 [temp.alias] paragraph 2

When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for the template-parameter s in the defining-type-id of the alias template.

This means that a template-id referring to an alias template performs a fresh substitution each time it appears. There is no concept of instantiating an alias template to produce an alias declaration. Subclause 13.7.8 [temp.alias] paragraph 5 specifies:

The type of a lambda-expression appearing in an alias template declaration is different between instantiations of that template, even when the lambda-expression is not dependent.

The outcome seems unfortunate; the first example ought to be well-formed.