具有多个可变参数模板的模板专业化

时间:2012-12-07 13:51:26

标签: c++ templates c++11 typetraits

在我的last question中,我获得了很大的帮助,可以让模板专业化工作。现在我需要一点延伸。我想要这些陈述的两个专业:

int main()
{
    // First specialization
    holder_ext<person> h1;
    holder_ext<person, &person::age> h2;
    holder_ext<int> h3;

    // Second specialization
    holder_ext<person, &person::age, &person::name> h4;
}

我的班级人员看起来像这样:

class person
{
private:
    std::string name_;
    int age_;
public:
    person(const std::string &name)
        : name_(name), age_(56)
    {}
    void age(int a) { age_ = i; }
    void name(const std::string &n) { name_ = n; }
};

特别之处在于,两个成员函数具有不同的参数类型。所以我不能为两者使用相同的可变参数模板成员函数。我尝试了两种不同的可变参数模板。但这不起作用。此外,成员函数的默认值也不起作用。

有人对我有好的暗示吗?

这是具有一个成员函数的解决方案(感谢Pubby):

template < class T, void (std::conditional<std::is_class<T>::value, T, struct dummy>::type::* ...FUNC)(int)> class holder;

template < class T, void (T::*FUNC)(int)>
class holder<T, FUNC>
{
public:
    explicit holder() : setter(FUNC) { std::cout << "func\n"; }
private:
    std::function<void (value_type&, int)> setter;
};

template < class T>
class holder<T>
{
public:
    explicit holder() { std::cout << "plain\n"; }
};

提前再次感谢!

P.S。:不,我不会在两天内出现“三个,四个,五个成员函数必须做什么”? ; - )

2 个答案:

答案 0 :(得分:0)

对于完全通用的解决方案,您将遇到无法解决的问题:无法推断非类型模板参数的类型,因此它必须在模板声明中是显式的,因此无法告知模板你想要多个指针到成员的参数,每个参数都有一个未知的类型。

我没有充分使用C ++ 11,但您可以尝试强制对成员模板参数进行排序并在模板中提供所有签名:

template <typename T, 
          void (std::conditional<...>::type*)(int),
          void (std::conditional<...>::type*)(const std::string&)>

同样,它可能会起作用,也可能不起作用......

答案 1 :(得分:0)

最后我找到了解决问题的方法。它是可变参数模板和模板规范之间的混合:

template < class T,
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::*FUNC1)(int) = nullptr,
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::* ...FUNC2)(const std::string&)
>
class holder_ext;

template < class T,
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::*FUNC1)(int),
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::*FUNC2)(const std::string&)
>
class holder_ext<T, FUNC1, FUNC2>
{
public:
    holder_ext() { std::cout << "func 2 test\n"; }
};

template < class T,
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::*FUNC1)(int)
>
class holder_ext<T, FUNC1>
{
public:
    holder_ext() { std::cout << "func 1 test\n"; }
};

我使用未实现的声明并定义两个特化。一个具有成员函数,另一个具有所有其他情况。

如果有更好的解决方案,请不要犹豫告诉我。