Search code examples
c++templateslambdalanguage-lawyer

Is it okay to use lambda as a default non-type template argument to generate unique types?


template <auto = [](){}>
struct A;

using unique_1 = A<>;
using unique_2 = A<>;

Is it safe to generate unique types like that or that's some sort of ill-formed behaviour?


Solution

  • Lambdas are never structural types and therefore trying to use a closure type of a lambda as a non-type template parameter's type is ill-formed. This has been clarified by CWG issue 2542.

    So the question of whether or not the template-ids A<> refer to different specializations becomes irrelevant.

    Compilers might not implement the defect report yet.

    However, by the current standard rules the following is possible:

    template<typename = void>
    using A = decltype([]{});
    
    using unique_1 = A<>;
    using unique_2 = A<>;
    

    There is an open CWG issue on the subject of changing this, because the rule permitting this behavior was intended to make it so that A<int> and A<float> are different types, not that every mention of A<int> will be a different type. That would seriously mess with ODR between translation units. Also there is compiler divergence. See CWG issue 2794.