Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ambiguous Function Calls to C++ base classes

Tags:

c++

c++11

I'm trying to create a variadic templated class which provides a method for each class in the typelist. An example is shown below which creates a print method for every class in the typelist:

#include <iostream>
#include <string>

// Helper class providing a function call
template <typename T>
class PrintHelper
{
public:
    void print(const T& t) { std::cout << t << std::endl; }
};

// Provides a print method for each type listed
template <typename... Ts>
class Printer : public PrintHelper<Ts>...
{};

int main()
{
    Printer<int, std::string> p;
    p.print(std::string("Hello World")); // Ambiguous Call
}

The commented line results in an error from GCC 4.6.3 on the commented line. What is the correct way to resolve the ambiguity or should I be looking at a different design?

like image 955
Peter Ogden Avatar asked Dec 13 '12 17:12

Peter Ogden


Video Answer


1 Answers

To resolve the ambiguity, it is possible to do

template <typename... Ts>
struct Printer : PrintHelper<Ts>...
{
    template <typename U>
    void print (const U& t)
    {
        PrintHelper<U>::print (t);
    }
};

(see an example )

but this is not quite as robust as one would hope. In particular, you cannot print an object which is convertible to one of the types from the type list.

With some template metaprogramming, it is possible to dispatch to the correct printer however. To do this you have to select a type from Ts... to which U is convertible, and call the right PrintHelper, ie.

PrintHelper<typename find_convertible<U, Ts...>::type>::print (t);

where find_convertible<U, Ts...> is defined by

template <typename U, typename... Ts>
struct find_convertible
{};

template <typename U, typename V, typename... Ts>
struct find_convertible<U, V, Ts...> :
    std::conditional<
        std::is_convertible<U, V>::value, 
        std::common_type<V>, // Aka identity
        find_convertible<U, Ts...>
    >::type
{};

(see example)

like image 121
Alexandre C. Avatar answered Oct 11 '22 13:10

Alexandre C.