I have a namespace with one highly templated free function, such as:
namespace a
{
template<typename T, typename K, typename H>
void f(T t, K k, std::vector<H> h_vec = {})
{ /* body */ }
}
Inside another namespace, for convenience I would like to have some aliases of it for a bunch of specific usages, such has:
namespace b
{
using my_specific_f = a::f<int,string,char>;
}
Which would allow me to provide a better naming for the function, since f
is very generic in the code base I am working on (please keep in mind I am providing only simplified examples here to make the point).
But unfortunately, this is apparently forbidden by the language.
So in my second attempt I tried to use a function pointer:
namespace b
{
auto my_specific_f = &a::f<int,string,char>
}
This would normally work, but in my case it does not since f
has one defaulted parameter, which I guess leads to the function having more than one function pointer (in this case two), and only the three parameter version can be used.
At this point I just gave up and simply made my_specific_f
redirect the call in its body to f
:
namespace b
{
void my_specific_f(int i, string s, vector<char> v = {} )
{
a::f(i,s,v);
}
}
But this solution I do not really like, as it leads to less maintainability in case f
will change its signature since all the redirecting functions need to be adapted concordantly, and my original plan was to create more than just one alias.
Is there anything left I could try? Is it even possible or will it be possible in some future release of the standard?
What you can do is wrap the fucntion in a generic lambda so you can give it a custom name. You can do that like
auto my_really_informative_name = [](auto&&... args) -> decltype(auto) {
return f(std::forward<decltype(args)>(args)...);
};
This perfectly forwards the parameters to f
and if it's signature ever changes it will still work since the lambda can take any number of arguments.
If you want to to be perfectly forwarding (noexcecpt qualification and return type in a SFINAE way)
auto my_really_informative_name = [](auto&&... args) noexcept(noexcept(f(std::forward<decltype(args)>(args)...))) -> decltype(f(std::forward<decltype(args)>(args)...)) {
return f(std::forward<decltype(args)>(args)...);
};
If you want to make sure the types passed to the function are of a certain type then you can specify them explicitly in the function call like
auto my_really_informative_name = [](auto&&... args) -> decltype(auto) {
return f<int, std::string, char>(std::forward<decltype(args)>(args)...);
};
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