C 变化宏或变异模板

C++ variadic macro or variadic template?

本文关键字:变异 变化      更新时间:2023-10-16

我想简化一些代码,并想帮助弄清楚是否有一种方法可以使用variadic宏或更好的variadic模板进行操作。下面的示例代码将显示我要做的事情。

#include <string>
#include <iostream>
#include <map>
#include <typeinfo>
// Class that registers an external function handler
template <typename ReturnType, typename... Args> class Redirector
{
    const std::string &m_funcName;
public:
    typedef ReturnType (*FuncTy)(Args...);
    Redirector(const std::string &functionName, FuncTy pfunc) : m_funcName(functionName)
    {
        GetMap()[functionName] = pfunc;
    }
    ~Redirector()
    {
        auto i = GetMap().find(m_funcName);
        if (i == GetMap().end()) return;
        i->second = nullptr;
        GetMap().erase(m_funcName);
    }
    static std::map<std::string, FuncTy> &GetMap()
    {
        static std::map<std::string, Redirector::FuncTy> _map;
        return _map;        
    }
    static FuncTy &GetHandler(std::string functionName)
    {
        auto i = GetMap().find(functionName);
        if (i == GetMap().end()) {
            std::cerr << functionName << " is not present in the list of functions to be redirected.n";
            exit(-1);
        }
        return i->second;
    }
};
// Actual functions we want to call
void foo(int a)
{
    std::cout << "foo:" << a << std::endl;
}
void bar(double b, int *p)
{
    std::cout << "bar:" << b << " and " << p << std::endl;
}

// Redirection Handlers 
void foo1(int A)
{
    auto handle = Redirector<void, int>::GetHandler("_FOO");
    handle(A);
}
Redirector<void, int>_FOOHandler("_FOO", reinterpret_cast<Redirector<void, int>::FuncTy>(foo));
void bar1(double B, int *P)
{
    auto handle = Redirector<void, double, int *>::GetHandler("_BAR");
    handle(B, P);
}
Redirector<void, double, int *>_BARHandler("_BAR", reinterpret_cast<Redirector<void, double, int *>::FuncTy>(bar));
// Main 
int main()
{
    int i = 7;
    foo1(i);
    bar1(3.4, &i);
    return 0;
}

假设会有很多foo1&amp;所需的BAR1函数和所有这些功能都会执行相同的功能,仅会采用不同数量的参数和不同类型的参数。以下不是一个工作的宏,而只是显示我要做什么的想法:

define REGISTER_HANDLER(NAME,PARAMS)
void NAME ## 1(PARAMS)                                                                              
{                                                                                                  
    auto handle = Redirector<PARAM_TYPES>::GetHandler("_"#NAME);                                   
    handle(PARAM_NAMES);                                                                                      
}                                                                                                   
Redirector<PARAM_TYPES>NAME ## Handler("_"#NAME, reinterpret_cast<Redirector<PARAM_TYPES>::FuncTy>(foo));
REGISTER_HANDLER(foo,int a);
REGISTER_HANDLER(bar,double b,int *p);

我已经考虑将__VA_ARGS__用于宏,但是我不太了解如何仅获取参数类型或参数名称。

我想我找到了一个有效的解决方案:

#define REGISTER_HANDLER(NAME,...)                                                                                          
template<typename... Args>                                                                                                  
void NAME##1(Args... args)                                                                                                  
{                                                                                                                           
    auto handle = Redirector<void, Args...>::GetHandler("_"#NAME);                                                          
    handle((args)...);                                                                                                      
}                                                                                                                           
Redirector<void,__VA_ARGS__>NAME ## HandlerObject("_"#NAME, reinterpret_cast<Redirector<void,__VA_ARGS__>::FuncTy>(NAME));
REGISTER_HANDLER(foo,int);
REGISTER_HANDLER(bar,double, int*);

如果有人有更好的主意,请告诉我。