I have several namespaces, each with the same set of function names:
namespace one {
void a();
void b();
void c();
}
namespace two {
void a();
void b();
void c();
}
namespace three {
void a();
void b();
void c();
}
Is there a nice way I can refactor the following code to avoid duplication?
one::a();
two::a();
three::a();
one::b();
two::b();
three::b();
while(true) {
one::c();
two::c();
three::c();
}
For example, in pseudocode, is there a way I can express
for (name: {one, two, three}) {
name::a();
}
cleanly?
I am also able to rewrite/restructure the function definitions, if there is a more idiomatic way to express the same idea.
You can't iterate through namespaces like that, but you could iterate through the different functions by explicitly listing them:
for (auto f : {one::a, two::a, three::a})
{
f();
}
If you need to do this a lot though, I'd probably just write a function in global scope to call all the others. Or you could write a macro to shorthand the list above:
#define func_list(name) {one::name, two::name, three::name}
for (auto f : func_list(a))
{
f();
}
It sort of depends on what you need to do in specific cases. However I would just suggest renaming them to be different or making differently-named wrapper functions in global scope.
If I have a full freedom on choosing mechanisms to use and c++14 compatible compiler I'd probably use tag dispatching + argument dependent lookup flavored with generic lambda to customize function call (choose the function to call afterwards):
#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);
}
output:
void one::a(one::Tag) void two::a(two::Tag) void three::a(three::Tag)
[live demo]
You could turn your namespaces into types.
struct one {
static void a();
static void b();
static void c();
};
struct two {
static void a();
static void b();
static void c();
};
struct three {
static void a();
static void b();
static void c();
};
Then to call all the a
functions, then all the b
functions, then all the c
functions:
template <typename... Namespaces>
void foo() {
(Namespaces::a(), ...); // expands into one::a(), two::a(), three::a()
(Namespaces::b(), ...);
(Namespaces::c(), ...);
}
foo<one, two, three>();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With