我有一个带有一个高度模板化的免费功能的名称空间,例如:
namespace a
{
template<typename T, typename K, typename H>
void f(T t, K k, std::vector<H> h_vec = {})
{ /* body */ }
}
在另一个命名空间中,为了方便起见,我想为一堆特定用法使用一些别名,例如:
namespace b
{
using my_specific_f = a::f<int,string,char>;
}
这将允许我为该函数提供更好的命名,因为f
在我正在研究的代码库中非常通用(请记住,我在这里仅提供简化示例以说明问题) 。
但不幸的是,这显然是语言所禁止的。
因此,在第二次尝试中,我尝试使用函数指针:
namespace b
{
auto my_specific_f = &a::f<int,string,char>
}
这通常可以正常工作,但是在我的情况下,由于f
具有一个默认参数,因此不起作用,我猜这会导致该函数具有一个以上的函数指针(在本例中为两个),而只有三个可以使用参数版本。
在这一点上,我只是放弃了,只是简单地将my_specific_f
内的呼叫重定向到f
:
namespace b
{
void my_specific_f(int i, string s, vector<char> v = {} )
{
a::f(i,s,v);
}
}
但是我并不喜欢这种解决方案,因为如果f
会更改其签名,因为所有重定向功能都需要进行协调调整,因此它的可维护性较差,我最初的计划是创建更多的解决方案一个别名。
还有什么我可以尝试的吗?在将来的标准发布中甚至有可能还是有可能?
答案 0 :(得分:10)
您可以做的是将功能包装在通用lambda中,以便为它自定义名称。您可以像这样
auto my_really_informative_name = [](auto&&... args) -> decltype(auto) {
return f(std::forward<decltype(args)>(args)...);
};
这可以完美地将参数转发到f
,并且如果签名发生更改,由于lambda可以接受任意数量的参数,因此仍然可以使用。
如果您想完美地转发(以SFINAE方式获得noexcecpt资格和返回类型)
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)...);
};
如果要确保传递给函数的类型是某种类型,则可以在函数调用中明确指定它们,例如
auto my_really_informative_name = [](auto&&... args) -> decltype(auto) {
return f<int, std::string, char>(std::forward<decltype(args)>(args)...);
};