如何在 C++ 中为函数名称分配别名?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3053561/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:54:36  来源:igfitidea点击:

How do I assign an alias to a function name in C++?

c++alias

提问by Agnel Kurian

It's easy to create a new name for a type, a variable or a namespace. But how do I assign a new name to a function? For example, I want to use the name hollerfor printf. #define is obvious... any other way?

为类型、变量或命名空间创建新名称很容易。但是如何为函数分配一个新名称呢?例如,我想将名称holler用于printf. #define 很明显......还有其他方式吗?

Solutions:

解决方案:

  1. #define holler printf
  2. void (*p)() = fn; //function pointer
  3. void (&r)() = fn; //function reference
  4. inline void g(){ f(); }
  1. #define holler printf
  2. void (*p)() = fn; //function pointer
  3. void (&r)() = fn; //function reference
  4. inline void g(){ f(); }

回答by sasha.sochka

There are different approaches:

有不同的方法:

  • With C++11 with non-template non-overloaded functions you can simply use:

    const auto& new_fn_name = old_fn_name;
    
  • If this function has multiple overloads you should use static_cast:

    const auto& new_fn_name = static_cast<OVERLOADED_FN_TYPE>(old_fn_name);
    

    Example: there are two overloads of function std::stoi

    int stoi (const string&, size_t*, int);
    int stoi (const wstring&, size_t*, int);
    

    If you want to make an alias to the first version you should use the following:

    const auto& new_fn_name = static_cast<int(*)(const string&, size_t*, int)>(std::stoi);
    

    Note:there is no way to make an alias to overloaded function such that all its overloaded versions work, so you should always specify which exact function overload you want.

  • With C++14 you can go even further with constexprtemplate variables. That allows you to alias templated functions:

    template<typename T>
    constexpr void old_function(/* args */);
    
    template<typename T>
    constexpr auto alias_to_old = old_function<T>;
    
  • Moreover, starting with C++11 you have a function called std::mem_fnthat allows to alias member functions. See the following example:

    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);
    
  • 使用带有非模板非重载函数的 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);
    

回答by Brian R. Bondy

You can create a function pointer or a function reference:

您可以创建函数指针或函数引用:

void fn()
{
}

//...

void (*p)() = fn;//function pointer
void (&r)() = fn;//function reference

回答by jer

typedef int (*printf_alias)(const char*, ...);
printf_alias holler = std::printf;

Should do you fine.

你应该没事吧。

回答by MSalters

int (*holler)(const char*, ...) = std::printf;

int (*holler)(const char*, ...) = std::printf;

回答by John

Use an inline wrapper. You get both APIs, but keep the single implementation.

使用内联包装器。您可以获得两个 API,但保留单个实现。

回答by sailfish009

From fluentcpp: ALIAS_TEMPLATE_FUNCTION(f, g)

来自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)...); \
}

回答by Kevin Anderson

It is worth mentioning here IMO that while the original question (and great answers) are definitely useful if you want to rename a function (there are good reasons to do so!), if all you want to do is strip out a deep namespace but keep the name, there is the usingkeyword for this:

在这里值得一提的是,如果您想重命名一个函数(有充分的理由这样做!),原始问题(和很好的答案)绝对有用,但如果您想做的只是去除深层命名空间,保留名称,有一个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
}

This also has the advantage of it being confined to a scope, though you could always use it at the top level of a file. I often use this for coutand endlso I don't need to bring in ALL of stdwith the classic using namespace std;at the top of a file, but also useful if you're using something like std::this_thread::sleep_for()a lot in one file or function, but not everywhere, and not any other functions from the namespace. As always, it's discouraged to use it in .h files, or you'll pollute the global namespace.

这还有一个优点是它被限制在一个范围内,尽管你总是可以在文件的顶层使用它。我经常使用它coutendl所以我不需要在文件顶部引入所有std经典using namespace std;,但如果你std::this_thread::sleep_for()在一个文件或函数中使用很多东西,但不是无处不在,这也很有用,并且不是命名空间中的任何其他函数。与往常一样,不鼓励在 .h 文件中使用它,否则会污染全局命名空间。

This is not the same as the "renaming" above, but is often what is really wanted.

这与上面的“重命名”不同,但通常是真正想要的。