Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从参数计数未知的函数创建函子 我在C++和Boost中编写了一个程序。是否可以编写一个模板类,从具有未知参数数的函数生成函子,例如my_call(vector),其中fun可以是bool-fun(string)或bool-fun(int,int,string),等等,重要的是要认识到,boost::variant是一个类模板,它需要包含所有可能的类型的列表。因此,您将不只是一个向量,而是一个向量,或者向量,您将无法混合它们_C++_Templates_Boost - Fatal编程技术网

从参数计数未知的函数创建函子 我在C++和Boost中编写了一个程序。是否可以编写一个模板类,从具有未知参数数的函数生成函子,例如my_call(vector),其中fun可以是bool-fun(string)或bool-fun(int,int,string),等等,重要的是要认识到,boost::variant是一个类模板,它需要包含所有可能的类型的列表。因此,您将不只是一个向量,而是一个向量,或者向量,您将无法混合它们

从参数计数未知的函数创建函子 我在C++和Boost中编写了一个程序。是否可以编写一个模板类,从具有未知参数数的函数生成函子,例如my_call(vector),其中fun可以是bool-fun(string)或bool-fun(int,int,string),等等,重要的是要认识到,boost::variant是一个类模板,它需要包含所有可能的类型的列表。因此,您将不只是一个向量,而是一个向量,或者向量,您将无法混合它们,c++,templates,boost,C++,Templates,Boost,这让我觉得您可能想使用boost::any而不是boost::variant。因此,我在这里提供了一个与boost::variant一起使用的解决方案,可以稍加修改以使用boost::any,因此您可以选择您喜欢的版本 首先,我必须承认解决方案使用起来很简单,但理解起来却不那么简单,因此我必须首先介绍一些机器。此机制对于基于变体和基于任意的解决方案都是通用的 //==================================================================

这让我觉得您可能想使用
boost::any
而不是
boost::variant
。因此,我在这里提供了一个与
boost::variant
一起使用的解决方案,可以稍加修改以使用
boost::any
,因此您可以选择您喜欢的版本


首先,我必须承认解决方案使用起来很简单,但理解起来却不那么简单,因此我必须首先介绍一些机器。此机制对于基于变体和基于任意的解决方案都是通用的

//=============================================================================
// META-FUNCTIONS FOR CREATING INDEX LISTS

// The structure that encapsulates index lists
template <size_t... Is>
struct index_list
{
};

// Collects internal details for generating index ranges [MIN, MAX)
namespace detail
{
    // Declare primary template for index range builder
    template <size_t MIN, size_t N, size_t... Is>
    struct range_builder;

    // Base step
    template <size_t MIN, size_t... Is>
    struct range_builder<MIN, MIN, Is...>
    {
        typedef index_list<Is...> type;
    };

    // Induction step
    template <size_t MIN, size_t N, size_t... Is>
    struct range_builder : public range_builder<MIN, N - 1, N - 1, Is...>
    {
    };
}

// Meta-function that returns a [MIN, MAX) index range
template<size_t MIN, size_t MAX>
using index_range = typename detail::range_builder<MIN, MAX>::type;
最后,简要演示如何使用此功能。假设我们有两个测试函数,如下所示:

#include <iostream>

bool test1(string s, double d)
{
    cout << s << " " << d << endl;
    return true;
}

bool test2(int i1, int i2, string s1, string s2)
{
    cout << i1 << " " << i2 << " " << s1 << " " << s2 << endl;
    return true;
}
由于所有调度员都有类型
dispatcher\u type
,因此您可以轻松地将其放入容器中。但是,您必须意识到这样一个事实,即只有在运行时才会检测到使用错误数量的参数调用函数的尝试(不可能在编译时知道一个
std::vector
包含多少元素)。因此,必须采取适当的措施


正如所承诺的,我现在将稍微修改此解决方案,以使用
boost::any
,而不是
boost::variant
。优点是,由于
boost::any
可以保存任何值,因此无需指定可用作函数参数的可能类型列表

在助手机制不变的情况下,核心调度器类模板必须修改如下:

#include <vector>
#include <functional>
#include <boost/any.hpp>

using namespace std;
using boost::any;

//=============================================================================
// DISPATCHER IMPLEMENTATION

template<typename R, typename... Args>
struct dispatcher
{

    template<typename F>
    dispatcher(F f) : _f(f) { }

    // The call operator which performs the dispatch
    R operator () (vector<any> const& v)
    {
        if (v.size() != sizeof...(Args))
        {
            // Wrong number of arguments provided!
            return false;
        }

        // Delegates to internal function call: needed for deducing
        // a sequence of integers to be used for unpacking.
        index_range<0, sizeof...(Args)> indexes;
        return do_call(v, indexes);
    }

private:

    // The heart of the dispatching mechanism
    template<size_t... Is>
    R do_call(vector<any> const& v, index_list<Is...> indexes)
    {
        return _f((get_ith<Args>(v, Is))...);
    }

    // Helper function that extracts a typed value from the variant.
    template<typename T>
    T get_ith(vector<any> const& v, size_t i)
    {
        return boost::any_cast<T>(v[i]);
    }

    // Wrapper that holds the function to be invoked.
    function<R(Args...)> _f;
};

// Helper function
template<typename R, typename... Args>
function<R (vector<any> const&)> get_dispatcher(R (*f)(Args...))
{
    dispatcher<R, Args...> d(f);
    return d;
}
唯一的缺点是使用
boost::any
无法显式分配字符串文字,因为字符串文字的类型为
char[]
,数组不能用于初始化
any
类型的对象:

any a = "hello"; // ERROR!
因此,您必须将它们包装到
string
对象中,或者显式地将它们转换为指向
char const*
的指针:

any a = string("hello"); // OK
any b = (char const*)"hello"; // OK

如果这对您来说不是一个大问题,那么最好采用第二种解决方案。

您能给出一个示例用例吗?我不太明白你的规格。
my_call
类是否重载了
operator()
向量的元素是否作为参数传递?你能用空括号调用函子吗?我有一个使用函数指针
事件(向量参数)
的回调哈希表。我想用一种普通的方式声明事件函数,比如
event_N(stringparam1,intparam2)
等等,并将函子推到哈希表中。模板可以帮助我不必手动编写每个函子类。您是否知道
variant
必须指定它可以保存哪些类型?所以它不仅仅是
variant
而是
variant
等等。没有匹配的调用函数«dispatcher::do_call(const std::vector&,index_range&)»候选函数是:模板bool dispatcher::do_call(const std::vector&,index_list)[带长无符号int…is={is…};Args={const string&,const string&}]模板参数推导/替换失败:转储不支持不匹配的类型«长无符号整数»和#«整数(cst)类型#索引列表未从索引派生_list@user1528805:与其向我抛出一个编译器错误,不如解释得更好一点好吗?您使用的是这两个版本中的哪一个?您使用的编译器是什么,版本是什么?@user1528805:Btw问题可能是使用了
unsigned int
而不是
size\u t
。我编辑了代码,试一下就可以了。
//=============================================================================
// META-FUNCTIONS FOR CREATING INDEX LISTS

// The structure that encapsulates index lists
template <size_t... Is>
struct index_list
{
};

// Collects internal details for generating index ranges [MIN, MAX)
namespace detail
{
    // Declare primary template for index range builder
    template <size_t MIN, size_t N, size_t... Is>
    struct range_builder;

    // Base step
    template <size_t MIN, size_t... Is>
    struct range_builder<MIN, MIN, Is...>
    {
        typedef index_list<Is...> type;
    };

    // Induction step
    template <size_t MIN, size_t N, size_t... Is>
    struct range_builder : public range_builder<MIN, N - 1, N - 1, Is...>
    {
    };
}

// Meta-function that returns a [MIN, MAX) index range
template<size_t MIN, size_t MAX>
using index_range = typename detail::range_builder<MIN, MAX>::type;
any a = "hello"; // ERROR!
any a = string("hello"); // OK
any b = (char const*)"hello"; // OK