1

I am still learning about up lambdas/templates/overloading and found this blog post by Nick Anthanasiou. There he method how to iterate over a tuple of different types, that behaves differently for every type.

I tested the code works fine by executing: clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out

However I ran into problems trying g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out

I get the following error:

request for member 'operator()' is ambiguous
   (void)expander{0, ((void)f(std::get<Is>(std::forward<Tuple>(tuple))), 0)...};

How can I fix the ambiguity, so it is also runable for g++?

#include <iostream>
#include <memory>
#include <algorithm>
#include <string>
#include <vector>
#include <type_traits>
#include <tuple>

using namespace std; 

template <class... F>
struct overload_set : F... 
{
  overload_set(F... f) : F(f)... {}  
};

template <class... F>
auto overload(F... f) 
{
  return overload_set<F...>(f...);   
}

template<class Func, class Tuple, size_t...Is>
void for_each_in_tuple(Func f, Tuple&& tuple, std::index_sequence<Is...>){
    using expander = int[];
    (void)expander { 0, ((void)f(std::get<Is>(std::forward<Tuple>(tuple))), 0)... };
}

template<class Func, class Tuple>
void for_each_in_tuple(Func f, Tuple&& tuple){
    for_each_in_tuple(f, std::forward<Tuple>(tuple),
               std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>());
}

int main()
{
    auto func = overload (
        [](int &val) { val *= 2; }, 
        [](string &arg) { arg += arg; }, 
        [](char &c) { c = 'x'; }
        );
    std::tuple<int, string, char> tup {1, "boom", 'a'};
    for_each_in_tuple(func, tup); 
    cout << get<0>(tup) << endl << get<1>(tup) << endl << get<2>(tup); 
}
xaxxon
  • 19,189
  • 5
  • 50
  • 80
Imago
  • 521
  • 6
  • 29
  • 1
    @JesperJuhl, can you be more rude and unhelpful? – Imago Aug 07 '18 at 21:12
  • 1
    you can't assume there always is a reasonable workaround ... compilers have point releases for a reason. – o11c Aug 07 '18 at 21:16
  • @o11c, how can one know there isn't that? I rather assume there is something I don't know or understand yet, than assume, that the problem is just too difficult, too advanced or simply that it cannot be done. In these cases I prefer talking to people and finding solutions. – Imago Aug 07 '18 at 21:21
  • 1
    It isn't clear why clang is accepting this. IMHO it should not, because thw ambiguity is real and prescribed by the standard (i.e. it's a bug in clang, not in gcc). – n. m. could be an AI Aug 07 '18 at 21:25
  • 2
    If you can pass to C++17, I propose to add a variadic `using` (non available in C++14) to `oveload_set`: `template struct overload_set : F... { using F::operator()...; overload_set (F ... f) : F(f)... {} };`; this seems to solve the problem for g++. – max66 Aug 07 '18 at 21:37
  • @xaxxon the accepted answer to the duplicate question explains it well. – n. m. could be an AI Aug 07 '18 at 21:39

0 Answers0