不明确的函数调用C++基类

Pet*_*den 16 c++ c++11

我正在尝试创建一个可变模板类,它为类型列表中的每个类提供一个方法.下面显示了一个示例,它print为类型列表中的每个类创建一个方法:

#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
}
Run Code Online (Sandbox Code Playgroud)

注释行导致GCC 4.6.3在注释行上出错.解决歧义的正确方法是什么,或者我应该考虑不同的设计?

Ale*_* C. 10

为了解决歧义,可以这样做

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

(见)

但这并不像人们希望的那样强大.特别是,您无法打印可转换为类型列表中某个类型的对象.

通过一些模板元编程,可以调度到正确的打印机.要做到这一点,你必须选择一个类型,从Ts...哪个U是敞篷车,并调用正确的PrintHelper,即.

PrintHelper<typename find_convertible<U, Ts...>::type>::print (t);
Run Code Online (Sandbox Code Playgroud)

在哪里find_convertible<U, Ts...>定义

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
{};
Run Code Online (Sandbox Code Playgroud)

(见)


Pet*_*den 8

我不喜欢回答我自己的问题,但我从这里的评论中创建了以下解决方案.它将所有print功能都纳入范围,并允许在所有功能上进行C++重载解析.

#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
{};

template<typename T>
class Printer<T> : public PrintHelper<T>
{
public:
    using PrintHelper<T>::print;
};

template<typename T, typename... Ts>
class Printer<T, Ts...>: public PrintHelper<T>, public Printer<Ts...>
{
public:
    using PrintHelper<T>::print;
    using Printer<Ts...>::print;
};

int main()
{
    Printer<int, std::string> p;
    p.print("Hello World"); // Not an ambiguous Call
}
Run Code Online (Sandbox Code Playgroud)