创建一个新类型、变量或命名空间的名称很容易,但如何给函数分配新名称呢?例如,我想用名称 holler
代替 printf
。使用 #define 很显然...还有其他方法吗?
解决方案:
#define holler printf
void (*p)() = fn; // 函数指针
void (&r)() = fn; // 函数引用
inline void g(){ f(); }
有不同的方法:
使用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
的函数来为成员函数创建别名。请看下面的例子:<\p><\li>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);
constexpr
模板变量的方法似乎存在问题:别名无法进行类型推导。编译器要求我提供模板参数列表(我正在编写一个可变参数模板函数):不能在没有模板参数列表的情况下引用变量模板“alias_to_old” - user69818constexpr auto new_fn_name = old_fn_name
在 C++11 中可行(至少在 gcc 4.9.2 中),比使用 &
更好。它不需要始终通过指针调用函数,因此允许将函数内联到调用的位置。 - ony`constexpr auto holler = [] ( auto &&...args ) {
return printf( std::forward( args )... );
};`
- Anthony Hallstd::mem_fn
并不是一个别名,因为它在幕后执行了更多的魔法。 - cgsdfc您可以创建函数指针或函数引用:
void fn()
{
}
//...
void (*p)() = fn;//function pointer
void (&r)() = fn;//function reference
fn
函数?你能解释一下函数指针和函数引用吗?它们有什么不同?在这里它们是相同的吗? - ma11hew28r();
- Agnel Kurianvoid (&r)() = this->fn;
- Samtypedef int (*printf_alias)(const char*, ...);
printf_alias holler = std::printf;
应该可以满足你的需求。
int (*holler)(const char*, ...) = std::printf;
constexpr auto holler = [] ( auto &&...args ) {
return printf( std::forward<decltype(args)>( args )... );
};
From 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)...); \
}
这里值得一提的是,如果你只想去除一个深层命名空间但保留名称,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
}
using namespace std;
,这样就不需要引入所有的std
,比如对于cout
和endl
。如果你在一个文件或函数中经常使用std::this_thread::sleep_for()
,但不是在每个地方使用,也不使用命名空间中的其他函数,那么它也很有用。一如既往,不建议在头文件中使用它,否则会污染全局命名空间。
void (&NewName)(some_vector&, float, float, float, float) = OldName;
。 - Agnel Kurianprintf
。那只是一个例子。这里的问题更多地与英语的限制有关而不是其他什么。我有一个函数,既可以用于目的A,也可以用于目的B,但我无法找到一个名称同时适用于两种情况。 - Agnel KurianT &a = b;
为b
创建了一个新名称。类型使用typedef
,命名空间使用namespace A=B;
。 - Agnel Kurianusing BaseClass::BaseClassMethod
,也有using AliasType = Type
,甚至有namespace AliasNamespace = Namespace
。我们所缺少的是using AliasFunction = Function
。 - anton_rh