Boost::Variant 和其中的 function_types:如何将函数放入 Boost::variant?

Posted

技术标签:

【中文标题】Boost::Variant 和其中的 function_types:如何将函数放入 Boost::variant?【英文标题】:Boost::Variant and function_types in it: How to put functions into Boost::variant? 【发布时间】:2011-11-29 20:35:31 【问题描述】:

歌词:

我尝试通过 MPI 实现任务池。所以我需要某种 RPC,但它可以在我的程序的不同部分之间工作,这意味着处理器 A 希望处理器 B 使用参数 D 调用函数 C。我们不能像处理线程那样在进程之间传递指向函数的指针,所以我们需要一些包装容器来保存每个流程实例的函数指针。都在一个源文件\一个程序中......所以我开始想知道How to store functional objects with different signature in a container。我当时的 API 想法是错误的 - 最好在该池构造中定义函数池中的所有函数(至少它应该更容易实现)。但是在实施时我遇到了下一个麻烦:

问题:

这么简单的代码(function_types、mpl::vector、variant):

#include <boost/function_types/function_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/variant.hpp>

#include <iostream>
#include <string>

template <class T>
int append(T val)

    std::cout << "hello";
    return 0;


int main()

    boost::variant<boost::function_types::function_type< boost::mpl::vector<int,int> >::type , boost::function_types::function_type< boost::mpl::vector<int,std::string> >::type  > a;
    return 0;
 

不会编译掉:

Error   1   error C2066: cast to function type is illegal   c:\program files\boost\include\boost\variant\variant.hpp    1231    1

看看source,我们看到了:

这个代码块:

variant()

    // NOTE TO USER :
    // Compile error from here indicates that the first bound
    // type is not default-constructible, and so variant cannot
    // support its own default-construction.
    //
    new( storage_.address() ) internal_T0();
    indicate_which(0); // zero is the index of the first bounded type

所以我想知道:如何解决这个错误?

我也试过了:

#include <boost/function_types/function_type.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/variant.hpp>
#include <boost/function.hpp>

#include <iostream>
#include <string>

template <class T>
int append(T val)

    std::cout << "hello";
    return 1;


int main()

    boost::variant< boost::function<int (std::string) >, boost::function<int (int) > > a;
    a= &append<int>;

    return 0;

失败的原因是:

Error   1   error C2668: 'boost::detail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node::initialize' : ambiguous call to overloaded function   c:\program files\boost\include\boost\variant\variant.hpp    1330

关于如何制作 boost.variant 保持函数的任何想法?

当然,我们可以像这样使用指向函子的共享指针:

#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>

#include <iostream>
#include <string>

template <class in, class out>
struct s_append

    out operator()(in val) 
        std::cout << "hello";
        return out();
    
;

int main()

    boost::variant<boost::shared_ptr<s_append<int, int> >, boost::shared_ptr< s_append<std::string, int> > > a;
    boost::shared_ptr<s_append<int, int> > b(new s_append<int, int> );
    a=b;
    return 0;

它会编译,但生成的 API 很糟糕——你必须 1)为你想使用的所有函数创建仿函数(意味着限制当前进程范围的使用); 2)使用shared_pointers,所以我什至不知道如何调用嵌套的函数(简单的第一个猜测(*a)(22);不会编译=(并且API开始像我们使用Boost.Any一样糟糕) .

【问题讨论】:

我不太明白与源代码有关的问题,但我认为您真正想要的是一些进程间通信。我建议你看看 Boost.Interprocess boost.org/doc/libs/1_48_0/doc/html/interprocess.html @manler:跨进程跨一台机器... MPI跨多台=) 是的,使用boost:bind() @myWallJSON 啊哈!当您提到 RPC 和 MPI 但在源代码中您使用的是 mpl(元编程)时,我想知道您的意思。那么源代码与这个问题有什么关系呢?为什么在变体中使用 mpl 向量? @manler:通常我想做this,但以this 之类的方式,所以我基于MPI 的集群间任务池会有很好的API。 【参考方案1】:

尝试插入一个虚拟类型作为variant 的第一个参数。正如您找到的评论所解释的那样,只有变体中的第一种类型用于变体自己的默认构造函数。您可以为此使用空结构类型 (struct NoFunction ;)。

也就是说,您可能已经想到使用 boost::functions 作为变体中的类型......它们至少是默认可构造的。我不确定您从该方法中遇到的其他错误是由什么引起的,但只是想让您知道,如果您不能使用我提到的虚拟类型解决方法,您可以更多地追求这个角度。

【讨论】:

以上是关于Boost::Variant 和其中的 function_types:如何将函数放入 Boost::variant?的主要内容,如果未能解决你的问题,请参考以下文章

为递归变体编写 boost::variant 访问者

Boost::variant 与引用相同变体的对象

boost::variant 与 bool 和 string

boost::variant 和多态性

boost::variant:递归向量类型的奇怪行为

强大的 boost::variant 序列化