4
#include <iostream> template<typename T> class A { }; template <typename T, typename T2, typename...Ts, typename = void > //^remove this compiles void func(T &&expr, T2 &&case1, Ts &&... args) { std::cout << "General\n"; } template <typename T, typename A_Type, typename...Ts, typename = void> //^remove this compiles auto func(T &&expr, A<A_Type>&&, Ts &&... args) { std::cout << "A<Type>\n"; } int main() { func(1, A<int>{}, 2); //ambiguous call } 

GCC 10.1 and older gives a ambiguous call error, but it compiles with 10.2. Demo here. I wonder if it's a bug on older version of GCC or my code is wrong and shouldn't compile.

The anonymous typename is for some SFINAE stuff, and I want a workaround to make it compile on older version of GCC.

1
  • Looks like a bug to me. Not 100% sure, but IIRC the second overload should be considered more specialized, so it should win in a tie scenario. Commented Oct 1, 2020 at 15:35

1 Answer 1

2

GCC Bug 96976 (Resolved; implemented in GCC 10.2, GCC 11)

This looks like GCC resolved bug

which was recently marked as resolved

Jonathan Wakely 2020-09-08 11:56:59 UTC

Fixed on trunk by r11-1571

It's also fixed on the gcc-10 branch by r10-8343

where the solution has been implemented for GCC 10.2 and 11.

Known to work: 10.2.0, 11.0


Workaround?

The anonymous typename is for some SFINAE stuff, and I want a workaround to make it compile on older version of GCC.

As is similarly asked and answered in the comments to the bug report:

Igor Chorazewicz 2020-09-08 12:17:32 UTC

[...] Also, do you by any chance, have any ideas how to workaround it for now?

**Vorfeed Canal 2020-09-09 13:32:20 UTC **

Why couldn't you use std::enable_if in it's usual (for functions) place?

Like this:

template <typename K, typename... Args> auto f(K&& k, Args&&... args) -> std::enable_if_t<true, void> { } 

you can remove the SFINAE-intended defaulted type template argument and apply SFINAE for the return type of the function instead, using trailing return type syntax.


Relevance to rvalue references?

Note that albeit the author of the bug report mentions problems with rvalue references in the title of the bug report, the failing example (fixed in GCC trunk) given in the report

#include <type_traits> template <typename... Args> void f(int &&a, Args&&... args) { } template <typename K, typename... Args, typename = typename std::enable_if<true, K>::type> void f(K&& k, Args&&... args) { } int main() { f(1, 2); return 0; } 

likewise fails(/is fixed) if we remove the rvalue references for the arguments of the f overloads, and these were likely not the root cause for this issue.

Sign up to request clarification or add additional context in comments.

4 Comments

Is there a way to SFINAE without specifying the type in the workaround? Because I still want auto to work
@szppeter Well, not really. To use sfinae, you'd have to disambiguate the calls somehow, and the workaround just does it in the trailing return type instead.
That will be quite hard for me. I have some if constexpr to return different type from the function.
@szppeter Ok, that may be an issue. Try solving it, and if it doesn't work out, post a new question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.