c ++,一种遍历树状结构的通用递归模板函数

sai*_*u78 5 c++ macros templates generic-lambda c++14

我尝试使用通用递归函数遍历树状结构,而不是每次为每个结构定义全局的递归函数.

//structure #1
class CA
{
public:
    std::string name;
    std::vector<CA*> vecChild;
};
Run Code Online (Sandbox Code Playgroud)

我用CA创建了一个树

auto root = new CA;
root->name = "root";
root->push_back(new CA);
auto& childA = root->back();
childA->name = "childA";
root->push_back(new CA);
auto& childB = root->back();
childB->name = "childB";
...
Run Code Online (Sandbox Code Playgroud)

我可以使用此宏来遍历此结构,这可以与其他树状结构一起使用.

#define Combinator(obj, combinatorObjToContainer, containerNameOfObj, invokingGetCount, combinatorContainerToIndexingItem, TAnyObject, TAnyContainer, argEnterFunc, argLeaveFunc)\
{\
    std::function<void(TAnyObject, TAnyContainer)> RecursFunc = [&](auto& argObj, auto& argContainer)\
    {\
        argEnterFunc(argObj, argContainer);\
        for(size_t idx=0; idx<argObj combinatorObjToContainer containerNameOfObj invokingGetCount; ++idx)\
        {\
            RecursFunc(argObj, argObj combinatorObjToContainer containerNameOfObj combinatorContainerToIndexingItem [idx]);\
        }\
        argLeaveFunc(argObj, argContainer);\
    }\
}
Run Code Online (Sandbox Code Playgroud)

它很难读,但它工作正常,我像这样遍历CA的根

Combinator(root, ->, vecChild, .size(), , CA*, std::vector<CA*>&, 
[&](auto& item, auto& vec)
{
    std::cout << item.name << std::endl;
},
[&](...)
{
});
Run Code Online (Sandbox Code Playgroud)

与其他结构一起使用,就像这样

struct MyData;
struct MyList
{
    int count;
    MyData* pItem;
};
struct MyData
{
    char* name;
    MyList* pLstChild;
};
Run Code Online (Sandbox Code Playgroud)

遍历MyData的根

Combinator(root, ->, pLstChild, ->count, ->pItem, MyData*, MyList*, 
[&](auto& pItem, auto& pLst)
{
    std::cout << pItem->name << std::endl;
},
[&](...)
{
});
Run Code Online (Sandbox Code Playgroud)

这里有一个主要问题.

我必须指定对象的类型及其容器,因为这里的lambda表达式是以递归形式定义的.

宏可以像模板函数一样推断出类型吗?或者我应该以其他方式实现这一目标?

max*_*x66 0

这里有一个大问题。

我必须指定对象及其容器的类型,因为这里的 lambda 表达式是以递归形式定义的。

宏可以像模板函数一样推导类型吗?

您确定需要宏吗?

在类(一种接口)中使用模板函数和一些具有固定名称的方法不是更好吗?

无论如何,如果我正确理解你的宏,TAnyObject你可以使用decltype(obj)而不是TAnyContainer你可以使用decltype(containerNameOfObj)

所以有些事情(抱歉:代码未经测试)

#define Combinator(obj, combinatorObjToContainer, containerNameOfObj, invokingGetCount, combinatorContainerToIndexingItem, argEnterFunc, argLeaveFunc)\
{\
    std::function<void(decltype(obj), decltype(containerNameOfObj))> RecursFunc = [&](auto& argObj, auto& argContainer)\
    {\
        argEnterFunc(argObj, argContainer);\
        for(size_t idx=0; idx<argObj combinatorObjToContainer containerNameOfObj invokingGetCount; ++idx)\
        {\
            RecursFunc(argObj, argObj combinatorObjToContainer containerNameOfObj combinatorContainerToIndexingItem [idx]);\
        }\
        argLeaveFunc(argObj, argContainer);\
    }\
}
Run Code Online (Sandbox Code Playgroud)