我有几个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>
的工厂函数的完全特化,但要么弄乱了语法,要么在编译时,编译器没有把它作为工厂。
还有其他想法吗?
答案 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});
我很惊讶可变参数模板不能更好地使用初始化列表。