为类型,变量或命名空间创建新名称很容易。但是如何为函数指定新名称?例如,我想为holler
使用名称printf
。 #define很明显......还有其他任何方式吗?
解决方案:
#define holler printf
void (*p)() = fn; //function pointer
void (&r)() = fn; //function reference
inline void g(){ f(); }
答案 0 :(得分:100)
有不同的方法:
对于带有非模板非重载函数的C ++ 11,您只需使用:
const auto& new_fn_name = old_fn_name;
如果此函数有多个重载,则应使用static_cast
:
const auto& new_fn_name = static_cast<OVERLOADED_FN_TYPE>(old_fn_name);
示例:函数std::stoi
int stoi (const string&, size_t*, int);
int stoi (const wstring&, size_t*, int);
如果要为第一个版本创建别名,则应使用以下内容:
const auto& new_fn_name = static_cast<int(*)(const string&, size_t*, int)>(std::stoi);
注意:无法为重载函数创建别名,使其所有重载版本都能正常工作,因此您应始终指定所需的确切函数重载。
使用C ++ 14,您可以更进一步使用constexpr
模板变量。这允许您为模板化函数添加别名:
template<typename T>
constexpr void old_function(/* args */);
template<typename T>
constexpr auto alias_to_old = old_function<T>;
此外,从C ++ 11开始,您有一个名为std::mem_fn
的函数,它允许别名成员函数。请参阅以下示例:
struct A {
void f(int i) {
std::cout << "Argument: " << i << '\n';
}
};
A a;
auto greet = std::mem_fn(&A::f); // alias to member function
// prints "Argument: 5"
greet(a, 5); // you should provide an object each time you use this alias
// if you want to bind an object permanently use `std::bind`
greet_a = std::bind(greet, a, std::placeholders::_1);
greet_a(3); // equivalent to greet(a, 3) => a.f(3);
答案 1 :(得分:33)
您可以创建函数指针或函数引用:
void fn()
{
}
//...
void (*p)() = fn;//function pointer
void (&r)() = fn;//function reference
答案 2 :(得分:21)
typedef int (*printf_alias)(const char*, ...);
printf_alias holler = std::printf;
你应该没事。
答案 3 :(得分:10)
int (*holler)(const char*, ...) = std::printf;
答案 4 :(得分:7)
使用内联包装器。您可以获得两个API,但保留单个实现。
答案 5 :(得分:2)
来自fluentcpp:ALIAS_TEMPLATE_FUNCTION(f,g)
#define ALIAS_TEMPLATE_FUNCTION(highLevelF, lowLevelF) \
template<typename... Args> \
inline auto highLevelF(Args&&... args) -> decltype(lowLevelF(std::forward<Args>(args)...)) \
{ \
return lowLevelF(std::forward<Args>(args)...); \
}
答案 6 :(得分:2)
使用C ++ 14通用lambda,我能够执行以下操作,当目标函数具有多个重载时,该方法也应工作:
constexpr auto holler = [] ( auto &&...args ) {
return printf( std::forward<decltype(args)>( args )... );
};
答案 7 :(得分:0)
在这里值得一提的是IMO,虽然如果您想重命名一个函数(有充分的理由!)的话,原始的问题(和很不错的答案)绝对有用,但是如果您想做的只是删除一个深名称空间,但保留名称,为此有一个using
关键字:
namespace deep {
namespace naming {
namespace convention {
void myFunction(int a, char b) {}
}
}
}
int main(void){
// A pain to write it all out every time
deep::naming::convention::myFunction(5, 'c');
// Using keyword can be done this way
using deep::naming::convention::myFunction;
myFunction(5, 'c'); // Same as above
}
这还具有将其限制在范围内的优势,尽管您始终可以在文件的顶层使用它。我经常将其用于cout
和endl
,因此我不需要将std
的全部与经典using namespace std;
一起放在文件顶部,但也很有用如果您在一个文件或函数中大量使用std::this_thread::sleep_for()
之类的东西,但不是在所有地方都使用,并且在命名空间中也不使用任何其他函数。与往常一样,不建议在.h文件中使用它,否则将污染全局名称空间。
这与上面的“重新命名”不同,但通常是真正需要的。