Code using core issue 2118: why doesn't Clang see the function definition?

Viewed 81

Sample code (taken from here [uses core issue 2118], slightly modified):

#include <type_traits>

template<int N> struct tag{};

template<typename T, int N>
struct loophole_t
{
    friend auto loophole(tag<N>) { return T{}; };
};

auto loophole(tag<0>);

struct detector
{
    template <typename T, int = sizeof(loophole_t<T, 0>)>
    operator T();
};

template <typename T, int = sizeof(T{detector{}})>
constexpr auto get_type()
{
    return loophole(tag<0>{});
}

typedef double T;

struct test
{
    T x;
};

int main(void)
{
    static_assert( std::is_same<T, decltype(get_type<test>())>::value, "xxx" );
    return 0;
}

Invocations:

$ gcc t0.cpp -std=c++14 -pedantic -Wall -Wextra
<nothing>

$ icc t0.cpp -std=c++14 -pedantic -Wall -Wextra
<nothing>

$ clang t0.cpp -std=c++14 -pedantic -Wall -Wextra
<source>:22:12: error: function 'loophole' with deduced return type cannot be used before it is defined
    return loophole(tag<0>{});
           ^
<source>:11:6: note: 'loophole' declared here
auto loophole(tag<0>);

$ cl t0.cpp /std:c++14 /Za
<nothing>

Why doesn't Clang see the function definition? What the standard says?

1 Answers

In your code

return loophole(tag<0>{});

is not dependent on a template parameter. I am unsure at the moment whether the standard requires that the type of loophole(tag<0>{}) be deduced at the point of the template definition, which would make the program ill-formed, but even if it doesn't, this is ill-formed, no diagnostic required.

[temp.res.general]/8.4 requires that a hypothetical instantiation of the template get_type immediately after its definition shall not be ill-formed due to a non-dependent construct. However, as mentioned above, the call to loophole(tag<0>{}) is non-dependent and could be ill-formed at this point due to the missing definition of loophole required to deduce the placeholder return type, if the default template argument is not used.

Related