4

Consider following C++ code:

#include <vector>

struct A {
    template<int Count, typename InputIt, typename OutputIt>
    static OutputIt func(InputIt first, OutputIt result) {
        // write some stuff to result...
        return result;
    }
};

template<typename Self>
struct Utils {
    template<int Count, typename InputIt>
    static std::vector<int> func(InputIt first) {
        std::vector<int> vec;
        Self::func<Count>(first, std::back_inserter(vec));
        return vec;
    }
};

struct C : A, Utils<C> {};

auto example(const char* ptr) {
    return C::func<20>(ptr);
}

godbolt.org link

A implements some functionality func() and Utils a helper function that simplifies the use of func() having the same name but one parameter less(!). C just combines those two into one struct.

Now, inside example() I would like to call the func() defined in Utils. However, gcc fails with the error "reference to 'func' is ambiguous" (clang also fails with a similar error message). I expect the compiler to be able to pick the correct func() since they differ in their number of parameters. What am I doing wrong here? How can I fix this without having to rename one of the functions?

Thanks!

shilch
  • 1,435
  • 10
  • 17

1 Answers1

3

You have two issues here. First, you need to explicitly pull in the func identifier from both base classes (necessary due to multiple inheritance):

struct C : A, Utils<C> {
    using A::func;
    using Utils<C>::func;
};

And next, you need a template keyword in Utils::func;

static std::vector<int> func(InputIt first) {
    std::vector<int> vec;
    Self::template func<Count>(first, std::back_inserter(vec));
    //    ^^^^^^^^
    return vec;
}

to disambiguate between the desired template instantiaion and another possible but weird expression (see here for more details).

lubgr
  • 37,368
  • 3
  • 66
  • 117