如何正确使用variadic模板功能

时间:2018-06-09 06:05:32

标签: c++ templates

我有一些结构和枚举看起来像这样:

enum NUM
{
   A = 0,
   B,
   C
};

struct X{};
struct Y{};

我想为一个看起来像这样的函数创建一个可变参数模板:

template<NUM n, typename...Args>
void func(const Args&...a);

我希望在以下情况下专门化模板函数func

如果NUM::Afunc定义为

template<> void func<A, X>(const X& x)
{
   var.emplace_back(std::make_shared<SomeClass>(x));
} 

如果NUM::Bfunc定义为

template<> void func<B,X,Y>(const X& x, const Y& y)
{
   var.emplace_back(std::make_shared<SomeOtherClass>(x,y))
}

你能帮我用可变参数模板整理一下吗?

1 个答案:

答案 0 :(得分:3)

函数的部分特化可以通过将函数的实现推迟到函数对象模板来实现,因为它是一个类模板,可以部分专门化。

示例:

#include <memory>
#include <vector>

enum NUM
{
   A = 0,
   B,
   C
};

struct X{};
struct Y{};

// guess at missing code in question

struct SomeBase
{
    virtual ~SomeBase() noexcept;
};

struct SomeClass : SomeBase
{
    SomeClass(const X&);
};

struct SomeOtherClass : SomeBase
{
    SomeOtherClass(const X&, const Y&);
};

std::vector<std::shared_ptr<SomeBase>> var;

// helper base class
struct func_impl_common
{
    func_impl_common(std::vector<std::shared_ptr<SomeBase>>& var) : var(var) {}
    std::vector<std::shared_ptr<SomeBase>>& var;
};

// general template
template<NUM n, typename...Args> struct func_impl;

// now specialise for A X
template<> struct func_impl<A, X> : func_impl_common
{
    using func_impl_common::func_impl_common;
    void operator()(X const& x) const
    {
       var.push_back(std::make_shared<SomeClass>(x));
    }
};

// now specialise for B X Y
template<> struct func_impl<B, X, Y> : func_impl_common
{
    using func_impl_common::func_impl_common;
    void operator()(X const& x, Y const& y) const
    {
       var.push_back(std::make_shared<SomeOtherClass>(x, y));
    }
};

// define func in terms of function object template

template<NUM n, typename...Args>
void func(const Args&...a)
{
    auto op = func_impl<n, Args...>(var);
    op(a...);
}

// test

int main()
{
    func<A>(X{});
    func<B>(X{}, Y{});
}

然而,如果这是一个真正的设计,它似乎有点怀疑。