在c++中循环命名空间中的所有函数

问题描述 投票:0回答:2

我的目标是迭代命名空间的所有函数,直到函数返回有效的策略(枚举)。每个函数可以采用不同的参数。

enum class strategyType
{
    Strategy1,
    Strategy2,
    Strategy3,
    Strategy4,
    Strategy5,
    InvalidStrategy
}

namespace allFunctionStrategy
{
   strategyType algorithmMl(int v1,int v2);
   strategyType algorithmHeuristic(int v3,string s1);
   strategyType algorithmHeuristic(string s1,string s2);
   ... n such function's
}

class strategyContext
{
    int v1,v2,v3;
    string s1,s2;

/*i want to add iterator logic here*/
}
c++ c++11 design-patterns c++17
2个回答
0
投票

编写一个调用它们的函数:

void strategyContext::execute() {
    if (algorithmM1(v1, v2) != strategyType::InvalidStrategy)
        ;
    else if (algorithmHeuristic(v3, s1) != strategyType::InvalidStrategy)
        ;
    else if (algorithmHeuristic(s1, s2) != strategyType::InvalidStrategy)
        ;
    else
        throw no_valid_strategy();
}

或者,如果“循环”一词是一个要求,则编写包装器并将函数指针放入数组中:

strategyType strategyContext::wrap_algorithmM1() {
    return algorithmM1(v3, s1);
}
strategyType strategyContext::wrap_algorithmHeuristic1() {
    return algorithmHeuristic(v3, s1);
}
strategyType strategyContext::wrap_algorithmHeuristic2() {
    return algorithmHeuristic(s1, s2);
}

typedef strategyType (strategyContext::*fptr)();
fptr pointers[] = {
    &strategyContext::wrap_algorithmM1,
    &strategyContext::wrap_algorithmHeuristic1,
    &strategyContext::wrap_algorithmHeuristic2
};

void strategyContext::execute() {
    for (auto iter = std::begin(pointers);
        iter != std::end(pointers);
        ++iter) {
    if ((this->*(*iter))() != strategyType::InvalidStrategy)
        return;
    }
    throw no_valid_strategy();
}

0
投票

好吧,首先,您可能不需要迭代命名空间中的每个函数。我将向您展示如何使用两个宏来实现基本反射,但您可能还应该重新考虑您想要做什么。另外,这将是非常混乱的代码。

首先,我们希望每个函数都采用相同的参数并返回相同的内容。对于您的用例,您可以将函数可以使用的所有参数添加到结构中。

struct PossibleParams
{
    //You can expand this if you want
    int x, y, z;  
};

struct Output {};

接下来,我们需要一个地方来存储函数。导入

functional
unordered_map
并添加以下宏。

#define ReflectableNamespace(name) namespace __REFLECTABLE__\
{ struct __NAMESPACE_ ## name ## __ { inline static std::unordered_map<std::string, std::function<Output(PossibleParams)>> funcs; }; \
    struct __ ## name ## _MAP_ADDER__ \
    {\
        __ ## name ## _MAP_ADDER__ (const std::string& Name, std::function<Output(PossibleParams)> func) { __NAMESPACE_ ## name ## __::funcs[Name] = func; }\
    };\
}\
namespace name

该宏的作用如下:

  1. 定义一个
    unordered_map
    ,它在函数名称和
    __REFLECTABLE__
    命名空间中的函数之间进行映射。
  2. 定义一个结构体,让我们在启动时通过其构造函数将函数添加到此映射中
  3. 开始您要创建的命名空间

第二个宏将声明一个可以迭代的函数并将其添加到函数映射中。

#define ReflectableFunction(namespace, name) Output name (PossibleParams);\
struct __NAMESPACE_ ## namespace ## _ ## name ## _adder__ {\
    inline static const __REFLECTABLE__::__ ## namespace ## _MAP_ADDER__ Adder = __REFLECTABLE__::__ ## namespace ## _MAP_ADDER__ (#name, name);\
}

第二个结构体声明一个返回

Output
并接受
PossibleParams
作为参数的函数。然后,它创建该命名空间的映射添加器对象的实例,以便该函数在启动时添加到命名空间的映射中。由于所有内容都是内联的,因此应该能够在头文件中使用。

要调用这些函数之一,只需使用

__REFLECTABLE__::__NAMESPACE_YourNamespace__::funcs["TheFunction"]({...});

完整的工作示例:

struct PossibleParams
{
    //Can expand this if you want
    int x, y, z;  
};

struct Output {};

#include <unordered_map>
#include <functional>

#define ReflectableNamespace(name) namespace __REFLECTABLE__\
{ struct __NAMESPACE_ ## name ## __ { inline static std::unordered_map<std::string, std::function<Output(PossibleParams)>> funcs; }; \
    struct __ ## name ## _MAP_ADDER__ \
    {\
        __ ## name ## _MAP_ADDER__ (const std::string& Name, std::function<Output(PossibleParams)> func) { __NAMESPACE_ ## name ## __::funcs[Name] = func; }\
    };\
}\
namespace name

#define ReflectableFunction(namespace, name) Output name (PossibleParams);\
struct __NAMESPACE_ ## namespace ## _ ## name ## _adder__ {\
    inline static const __REFLECTABLE__::__ ## namespace ## _MAP_ADDER__ Adder = __REFLECTABLE__::__ ## namespace ## _MAP_ADDER__ (#name, name);\
}

#include <iostream>
ReflectableNamespace(MyNamespace)
{
    ReflectableFunction(MyNamespace, func);
    
    Output func(PossibleParams)
    {
        std::cout << "Hello" << std::endl;
        return {};
    }
}



int main()
{
    std::cout << __REFLECTABLE__::__NAMESPACE_MyNamespace__::funcs.size() << std::endl;
    __REFLECTABLE__::__NAMESPACE_MyNamespace__::funcs["func"]({});

    return 0;
}

最后一件事。如果您计划多次迭代此地图,最好将其替换为普通的

map
,因为迭代速度可能会更快。或者,如果您不关心函数的名称,您可以考虑用向量替换映射。我希望这有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.