c++ - 如何使用 boost fusion 容器中实例化的类型的参数调用构造函数?

标签 c++ boost

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

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

相关文章:

c++ - 如何加快 OpenCV 代码的实现速度

c++ - 如何写入 boost::asio::mutable_buffer?

c++ - 图中的路径数

c++ - 如何将字符数组的一部分附加到字符串?

c++ - 为什么 parse_config_file 在流上设置 failbit?

c# - 打开 URL 的自定义图标

c++ - 更好的 Boost 引用?

c++ - FFT 窗口导致频谱放大不均

C++ boost序列化多态问题

C++ boost库无法打开文件