在命名空间列表中调用具有相同名称的函数

yoy*_*yoy 7 c++

我有几个命名空间,每个命名空间都具有相同的函数名称集:

namespace one {
void a();
void b();
void c();
}

namespace two {
void a();
void b();
void c();
}

namespace three {
void a();
void b();
void c();
}
Run Code Online (Sandbox Code Playgroud)

有没有一种很好的方法可以重构以下代码以避免重复?

one::a();
two::a();
three::a();

one::b();
two::b();
three::b();

while(true) {
  one::c();
  two::c();
  three::c();
}

Run Code Online (Sandbox Code Playgroud)

例如,在伪代码中,有没有一种方法可以表达

for (name: {one, two, three}) {
  name::a();
}
Run Code Online (Sandbox Code Playgroud)

干净吗?

如果有更惯用的方式来表达相同的想法,我也可以重写/重组函数定义。

Cru*_*ean 11

您不能像那样遍历命名空间,但可以通过显式列出它们来遍历不同的函数:

for (auto f : {one::a, two::a, three::a})
{
    f();
}
Run Code Online (Sandbox Code Playgroud)

如果你需要这样做很多,我可能只是在全局范围内编写一个函数来调用所有其他函数。或者您可以编写一个宏来速记上面的列表:

#define func_list(name) {one::name, two::name, three::name}

for (auto f : func_list(a))
{
    f();
}
Run Code Online (Sandbox Code Playgroud)

这有点取决于您在特定情况下需要做什么。但是,我只是建议将它们重命名为不同的或在全局范围内创建不同名称的包装器函数。


W.F*_*.F. 2

如果我可以完全自由地选择要使用的机制和 c++14 兼容编译器,我可能会使用标记分派 + 带有通用 lambda 的参数相关查找来自定义函数调用(选择随后要调用的函数):

#include <iostream>

namespace one {
struct Tag { } tag;
void a(Tag) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
void b(Tag) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
void c(Tag) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
}

namespace two {
struct Tag { } tag;
void a(Tag) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
void b(Tag) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
void c(Tag) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
}

namespace three {
struct Tag { } tag;
void a(Tag) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
void b(Tag) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
void c(Tag) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
}

template <class L, class... Ts>
void foreach(L&& l, Ts&& ...ts) {
    int execute[] = { 0, (l(ts), 1)... };
    static_cast<void>(execute);
}

int main() {
    foreach([](auto tag) { a(tag); }, one::tag, two::tag, three::tag);
}
Run Code Online (Sandbox Code Playgroud)

输出:

void one::a(one::Tag)
void two::a(two::Tag)
void three::a(three::Tag)
Run Code Online (Sandbox Code Playgroud)

[现场演示]