我的目标是迭代命名空间的所有函数,直到函数返回有效的策略(枚举)。每个函数可以采用不同的参数。
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*/
}
编写一个调用它们的函数:
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();
}
好吧,首先,您可能不需要迭代命名空间中的每个函数。我将向您展示如何使用两个宏来实现基本反射,但您可能还应该重新考虑您想要做什么。另外,这将是非常混乱的代码。
首先,我们希望每个函数都采用相同的参数并返回相同的内容。对于您的用例,您可以将函数可以使用的所有参数添加到结构中。
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
该宏的作用如下:
unordered_map
,它在函数名称和 __REFLECTABLE__
命名空间中的函数之间进行映射。第二个宏将声明一个可以迭代的函数并将其添加到函数映射中。
#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
,因为迭代速度可能会更快。或者,如果您不关心函数的名称,您可以考虑用向量替换映射。我希望这有帮助!