这是一个说明问题的简单示例:
// 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?
}
最佳答案
就像评论者说的那样,问题出在哪里,您将从中获取值(value)。现在,我假设您的意思是您知道要为“默认”构造传递哪些值(即使从技术上说,没有默认构造函数)。
为此,可以使用特征:
namespace mytraits {
template <typename T>
struct elem_construct {
static T call() { return T(); }
};
}
如您所见,
elem_construct::call
的默认实现仅调用默认的构造函数 [1] 。现在,如何为每个 vector 元素调用此特征?
在一个完美的世界中(阅读:Boost Fusion以真正的C++ 11风格使用variadics),这很简单
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/