sfinae with decltype: bug in clang or gcc?

前端 未结 1 1620
伪装坚强ぢ
伪装坚强ぢ 2021-02-14 11:17

Clang-3.2 can compile and code behave as expected:

struct have_f { int f(int i) {return 10;} }; 

struct empty {};

template  
struct outer {
             


        
相关标签:
1条回答
  • 2021-02-14 11:57

    I believe the issue is 14.6.3 [temp.nondep]:

    1 - Non-dependent names used in a template definition are found using the usual name lookup and bound at the point they are used.

    The example given describes that an ill-formed expression within the template definition "could be diagnosed either [in the template definition] or at the point of instantiation".

    The default template-argument (14.1p9) U=decltype(t.f(1)) is a non-dependent name within the context of the instantiation of struct outer (that is, it does not depend on a template argument to its own template) so it is ill-formed for the instantiation of struct outer with T = struct empty. The standard doesn't explicitly describe where default template-arguments are evaluated, but the only sensible conclusion is that they are treated as any other construct and evaluated at the point they occur (or, in this example, at the point of instantiation of the struct outer template). I don't see any latitude for the compiler to delay evaluation of non-dependent default template-arguments to contexts where SFINAE applies.

    Fortunately the solution is easy: just make the default template-argument U a dependent name:

        // if T have f(), define  outer_f()
        template<class T2 = T, class U=decltype(static_cast<T2 &>(t).f(1))> 
        int outer_f(int i) { return t.f(i); }
    
    0 讨论(0)
提交回复
热议问题