简体   繁体   English

C ++可变参数宏还是可变参数模板?

[英]C++ variadic macro or variadic template?

I would like to simplify some code and would like help figuring out if there is a way to do it with a variadic macro or better yet a variadic template. 我想简化一些代码,并希望帮助您确定是否有一种方法可以使用可变参数宏或更好的可变参数模板。 The sample code below will show what I am trying to do. 下面的示例代码将显示我正在尝试做的事情。

#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;
}

Assume there will be lots of foo1 & bar1 functions that are needed and all of them would do the same just would take different number of parameters and different types of parameters. 假设将需要很多foo1和bar1函数,并且它们都将执行相同的操作,只是需要使用不同数量的参数和不同类型的参数。 The following is not a working macro but just an idea to show what I am trying to do: 以下不是有效的宏,而仅仅是一个说明我正在尝试做的事情:

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);

I have looked into using the __VA_ARGS__ for macros, but I can't quite figure out how to get just the parameter types or just the parameter names. 我已经研究过将__VA_ARGS__用于宏,但是我还不太清楚如何获取参数类型或参数名称。

Well I think I found a solution that works: 好吧,我想我找到了一个可行的解决方案:

#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*);

If someone has a better idea please let me know. 如果有人有更好的主意,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM