这是一个说明问题的简单示例:

// 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/

10-12 15:42