初始化列表作为可变参数模板参数

时间:2015-11-30 16:26:26

标签: c++11 variadic-templates

我有几个A,B和F类,都有不同的构造函数签名,如下所示:

class A {
public:
     A() {}
};

class B {
    double x_, y_;
public:
    B(double x, double y) : x_(x), y_(y) {}
};

class F {
    vector<unsigned> factors_;
public:
    F(std::initializer_list<unsigned> factors) : factors_(factors) {}
};

这些类的对象需要在某处注册,因此构造应该通过工厂,如下所示:

template<class R, typename... Args>
inline R & factory(Args &&... args)
{
    R * rp = new R(std::forward<Args>(args)...);
    /* do fancy stuff with rp... */
    return *rp;
}

这适用于A类和B类,但不适用于F,因为typename ...想要采用一种或多种类型:

A & a = factory<A>();   // okay     
B & b = factory<B>(0.707107, 0.707107);  // okay
F & f = factory<F>({2, 3, 5, 7, 11});  // error: no matching function for call to ‘F::F()’ in factory

问题:有没有办法让它与常规factory<R>(args...)语法一起使用?

我尝试了<F, std::initializer_list>的工厂函数的完全特化,但要么弄乱了语法,要么在编译时,编译器没有把它作为工厂。

还有其他想法吗?

2 个答案:

答案 0 :(得分:1)

回答这个问题:我看不到一种简单的方法来重复使用带有initializer_list的工厂方法。

我个人会在F级中添加std::vector

的构造函数
F(const std::vector<unsigned>& factors) : factors_(factors) {}

并重写工厂方法:

template<class R>
inline R & factory(const std::vector<unsigned>& factors)
{
    R *rp = new R(factors);
    /* do fancy stuff with rp... */
    return *rp;
}

现在编译得很好。

<强> Live code

如果您想避免代码重复,您应该考虑在另一个函数中编写/* do fancy stuff with rp... */

修改

我不知道你想做什么,但你为什么不在这里使用:

F f2{2, 3, 5, 7, 11};

如果您只想使用某些值填充F类向量,则不需要工厂。

答案 1 :(得分:0)

它可能不是您首选的语法,但您可以强制工厂方法传递初始值设定项列表:

F & f = factory<F>(std::initializer_list<unsigned>{2u, 3u, 5u, 7u, 11u});

我在这里明确地将文字设为无符号 - 虽然它们可以由std::initializer_list<unsigned>强制执行,但不是以下版本的情况。

我能够使用factory()的重载:

template<class R>
inline R& do_fancy_stuff_with(R *r)
{
    /* do fancy stuff here... */
    return *r;
}

template<class R, typename... Args>
inline R & factory(Args &&... args)
{
    R * rp = new R(std::forward<Args>(args)...);
    return do_fancy_stuff_with(rp);
}

template<class R, typename T>
inline R & factory(std::initializer_list<T> args)
{
    R * rp = new R(std::move(args));
    return do_fancy_stuff_with(rp);
}

A & a = factory<A>();
B & b = factory<B>(0.707107, 0.707107);
F & f = factory<F>({2u, 3u, 5u, 7u, 11u});

我很惊讶可变参数模板不能更好地使用初始化列表。