这是一个说明问题的简单示例:
// this class requires a parameter to its constructor
class A
{
A() = delete;
A(int x) {}
};
using B = A;
using C = A;
using Vector = boost::fusion::vector<A, B, C>;
// somewhere else in my code
template <typename FusionVector>
void fun()
{
// I need to instantiate this vector here, and initialise each element with some integer.
// I _know_ what parameters the types take, but I have no idea what types they are
// or how many of them there are. Can I do this?
FusionVector vec; // this won't work...
}
int main()
{
int x = 10; // I want to construct all types in Vector with this value
fun<Vector>(); // how do I do that?
}
最佳答案
正如评论者所说,问题在于您将从哪里获取值。现在,我假设您的意思是您知道要为“默认”构造传递哪些值(即使从技术上讲,没有默认构造函数)。
为此目的,您可以使用特征:
namespace mytraits {
template <typename T>
struct elem_construct {
static T call() { return T(); }
};
}
如您所见,elem_construct::call
的默认实现仅调用默认构造函数[1]。
现在,如何为每个 vector 元素调用此特征?
在一个完美的世界中(阅读:Boost Fusion 使用真正的 C++11 风格的可变参数),这会很简单
template <typename FusionVector> struct fun_helper;
template <typename... Ts>
struct fun_helper<boost::fusion::vector<Ts...> > {
static typename boost::fusion::vector<Ts...> call() {
return { std::move(mytraits::elem_construct<Ts>::call())... };
}
};
但是,这会失败,因为 Boost Fusion 支持 C++03 并且没有真正的变量。因此,推导出 10 个 [2] 模板参数,我们最终将传递 3 个 A
实例以及 7 个 boost::fusion::void_
类型的实例...是的。这实际上不起作用。
因此,要克服一些困难来安抚编译器:
namespace detail {
template <typename... Ts>
struct internal_fun_helper {
static typename boost::fusion::vector<Ts...> call() {
return boost::fusion::vector<Ts...> (std::move(mytraits::elem_construct<Ts>::call())...);
}
};
// helpers that detect the real cardinality of vectors even in the presence of C++03 faux variadics
// {{{ plumbing
template <typename FusionVector> struct fun_helper;
template <typename T1>
struct fun_helper<boost::fusion::vector<T1> > {
static typename boost::fusion::vector<T1> call() { return internal_fun_helper<T1>::call(); }
};
template <typename T1, typename T2>
struct fun_helper<boost::fusion::vector<T1,T2> > {
static typename boost::fusion::vector<T1,T2> call() { return internal_fun_helper<T1,T2>::call(); }
};
// etc. - you get the idea
现在您可以使用 fun
分派(dispatch)特化:
template <typename FusionVector> FusionVector fun() {
return detail::fun_helper<FusionVector>::call();
}
一切正常,请参阅此演示 Live On Coliru
// here's the magic that tells our `fun` factory how to construct A
namespace mytraits {
template <>
struct elem_construct<A> { static A call() { return A(42); } };
}
#include <boost/phoenix.hpp>
using boost::phoenix::arg_names::arg1;
int main()
{
boost::fusion::for_each(fun<boost::fusion::vector<A, B, C>>(), std::cout << arg1 << "\n");
}
打印输出
A[42]
A[42]
A[42]
[1](或值初始化原始类型和聚合的 T)。
[2] 取决于预处理器定义,但 10 是默认限制(请参阅 FUSION_MAX_VECTOR_SIZE
)
关于c++ - 如何使用 boost fusion 容器中实例化的类型的参数调用构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26138079/