I have this piece of code:
template <int N>
struct flag {
friend constexpr int adl_flag(flag<N>); //function prototype
};
template <int N>
struct writer {
// Template instantiation "implements" adl_flag function.
friend constexpr int adl_flag(flag<N>) { return N; }
// Accessing this constant forces this struct to be instantiated.
static constexpr int value = N;
};
template <int N, int M = adl_flag(flag<N>{})>
int constexpr reader(int, flag<N>, int R = reader(0, flag<N + 1>{}))
{
// When adl_flag(flag<N>) has already been implemented, overload resolution prefers this one and
// in turn the default parameter triggers adl_flag(flag<N+1>) to be called
return R;
}
template <int N>
int constexpr reader(float, flag<N>)
{
// When adl_flag(flag<N>) has not been implemented yet, the overload above results in substitution failure and this one is chosen, and the recursion stops.
//This function thus returns the lowest N that adl_flag(flag<N>) has not been implemented yet.
return N;
}
template <int N = 0,int R = reader<N>(0, flag<N>{})>
int constexpr next(int next=writer<R>::value)
{
//This function queries the next N that adl_flag(flag<N>) is not implemented, and then implements it.
//These all happens in the evaluation of default parameters, which is guaranteed to be executed every time this function is called with default parameters.
return next;
}
int main()
{
static_assert(next()==0,"Wrong result");
static_assert(next()==1,"Wrong result");
static_assert(next()==2,"Wrong result");
static_assert(next()==3,"Wrong result");
}
This basically implements "constexpr counter". This worked great and the static_assert's passed with compile options "-std=gnu++11"...until g++ 8.1.
Since g++ 8.1, this code no longer works. Instead, it seems that
static_assert(next()==0,"Wrong result");
static_assert(next()==1,"Wrong result");
static_assert(next()==1,"Wrong result");
static_assert(next()==1,"Wrong result");
this passes the compilation.
Can anyone explain what happened to g++ compiler? Is it a bugfix in g++ 8.1? or is it a bug that is introduced in g++ 8.1?