2

In the code below, I constructed the most minimal example I could where g++ (tested with both versions 9.4 and 8.4) triggers a compilation error due to an ambiguous overload on the function f that (to me) doesn't appear to be ambiguous:

<source>:45:25: error: call of overloaded 'f(std::tuple<select_type<int, int>, select_type<double, char> >&, select_type<int, variadic_type<variadic_entry<int>, variadic_index<0, 0> > >&)' is ambiguous
   45 |     auto f1 = f(tupl, v1); // g++ says ambiguous?
      |                         ^
<source>:28:6: note: candidate: 'auto f(std::tuple<select_type<T1s, T2s>...>, const select_type<T0, variadic_type<variadic_entry<T10>, T11> >&) [with T1s = {int, double}; T2s = {int, char}; T0 = int; T10 = int; T11 = variadic_index<0, 0>]'
   28 | auto f(std::tuple<select_type<T1s, T2s>...>, select_type<T0, variadic_type<variadic_entry<T10>, T11>> const&)
      |      ^
<source>:34:6: note: candidate: 'auto f(std::tuple<select_type<T1s, T2s>...>, const select_type<T0, variadic_type<variadic_entry<T10>, variadic_index<I10, I11> > >&) [with T1s = {int, double}; T2s = {int, char}; T0 = int; T10 = int; int I10 = 0; int I11 = 0]'
   34 | auto f(std::tuple<select_type<T1s, T2s>...>, select_type<T0, variadic_type<variadic_entry<T10>, variadic_index<I10, I11>>> const&)
      |      ^

Moreover, msvc and clang both accept it and can select the correct overload.

#include <tuple>

template<typename... Ts>
struct variadic_type {};

template<typename T>
struct variadic_entry {};

template<int I0, int I1>
struct variadic_index {};

template<typename T0, typename T1>
struct select_type {};

template<typename T0, typename T10, typename T11>
struct select_type<T0, variadic_type<variadic_entry<T10>, T11>> 
{
    select_type(T0 = {}, variadic_type<variadic_entry<T10>, T11> = {}) {}
};

template<typename T0, typename T10, int I10, int I11>
struct select_type<T0, variadic_type<variadic_entry<T10>, variadic_index<I10, I11>>> 
{
    select_type(T0 = {}, variadic_type<variadic_entry<T10>, variadic_index<I10, I11>> = {}) {}
};

template<typename... T1s, typename... T2s, typename T0, typename T10, typename T11>
auto f(std::tuple<select_type<T1s, T2s>...>, select_type<T0, variadic_type<variadic_entry<T10>, T11>> const&)
{
    return 0;
}

template<typename... T1s, typename... T2s, typename T0, typename T10, int I10, int I11>
auto f(std::tuple<select_type<T1s, T2s>...>, select_type<T0, variadic_type<variadic_entry<T10>, variadic_index<I10, I11>>> const&)
{
    return 1;
}

int main()
{
    auto tupl = std::make_tuple(select_type<int, int>{}, select_type<double, char>{});
    auto v0 = select_type<int, variadic_type<variadic_entry<int>, variadic_entry<void>>>{};
    auto v1 = select_type<int, variadic_type<variadic_entry<int>, variadic_index<0, 0>>>{};
    auto f0 = f(tupl, v0);
    auto f1 = f(tupl, v1); // g++ says ambiguous?
}

The curiousity of this example that I've noticed in experimenting is:

  1. If the tuple argument is simply put as std::tuple<Ts...> rather than std::tuple<select_type<T1s, T2s>...>, then there is no ambiguity and the correct overload is selected;
  2. If there is no tuple argument, then again there is no ambiguity.

I have extensively looked through the many ambiguous template issues on this site and elsewhere to understand this problem (and ideally correct it), but I wasn't able to. It would be much appreciated if this could be explained.

If it helps, the error is also replicated by pasting the code into https://www.programiz.com/cpp-programming/online-compiler/.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
Riddick
  • 319
  • 3
  • 15
  • 1
    I've edited the questions to add more detail. The compiler version is `g++ 9.4`, and the online compiler (https://www.programiz.com/cpp-programming/online-compiler/) also replicates the error. – Riddick Jun 12 '23 at 22:13
  • 3
    Reduced: https://godbolt.org/z/3ne16nEzv Looks like a gcc bug – Artyer Jun 12 '23 at 22:17
  • 1
    Found this question which seems to be the same issue: https://stackoverflow.com/q/32025188 along with this bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67228 – Artyer Jun 12 '23 at 22:49

0 Answers0