https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80737
--- Comment #6 from Tim Shen <timshen at gcc dot gnu.org> --- (In reply to TC from comment #5) > (In reply to Tim Shen from comment #3) > > (In reply to TC from comment #1) > > > Looks like the constraint on the convert-everything constructor needs to > > > check for is_same<decay_t<_Tp>, variant> first and short circuit if that's > > > true. > > > > I'm not quite sure whether we need that short circuit - it's in a SFINAE > > environment, so if anything goes wrong, there shouldn't be a hard error. > > Therefore even if I agree that we should check is_same<decay_t<_Tp>, > > variant> first, that shouldn't affect the correctness. > > I'm not sure I agree. As http://stackoverflow.com/a/43963065/2756719 points > out, when you attempt to copy a variant<any>, as part of overload resolution > the code attempts to check if you can convert a variant<any> to any; that in > turn queries whether variant<any> is copy constructible, On this part I agree, that is: if there isn't a short circuiting, then a instantiation circle will happen: variant(_Tp&&), then any(const variant<any>&), then is_nothrow_move_constructible<variant<any>>, then variant(_Tp&&). > and we are very close to turtling all the way down. The question is: how does the compiler handle an instantiation circle, and can we rely on that handling? Clang sees the instantiation circle and bailed out nicely, bascically rewinds the instantiation stack and SFINAEed out variant(_Tp&&). However, GCC issued a hard error. I asked Richard Smith about what's the intended behavior here, and the answer is that the standard doesn't talk about this. > > It does seem like there might be a frontend problem here, though. To conclude, there is a front-end implementation mismatch that cause this code not to compile on GCC. For consistency with other places in libstdc++, I'll short-circuit the SFINAE expression. In addition, https://godbolt.org/g/AxUv16 reveals a weird GCC behavior (with/without -DBUG) that might be a separate bug.