如何在C++中为函数名指定别名?

Agn*_*ian 92 c++ alias

为类型,变量或命名空间创建新名称很容易.但是如何为函数指定新名称?例如,我想使用的名称holler进行printf.#define很明显......还有其他方式吗?

解决方案:

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

sas*_*hka 106

有不同的方法:

  • 使用带有非模板非重载函数的C++ 11,您可以简单地使用:

    const auto& new_fn_name = old_fn_name;
    
    Run Code Online (Sandbox Code Playgroud)
  • 如果此函数有多个重载,您应该使用static_cast:

    const auto& new_fn_name = static_cast<OVERLOADED_FN_TYPE>(old_fn_name);
    
    Run Code Online (Sandbox Code Playgroud)

    示例:函数有两个重载 std::stoi

    int stoi (const string&, size_t*, int);
    int stoi (const wstring&, size_t*, int);
    
    Run Code Online (Sandbox Code Playgroud)

    如果要为第一个版本创建别名,则应使用以下内容:

    const auto& new_fn_name = static_cast<int(*)(const string&, size_t*, int)>(std::stoi);
    
    Run Code Online (Sandbox Code Playgroud)

    注意:无法为重载函数创建别名,使其所有重载版本都能正常工作,因此您应始终指定所需的确切函数重载.

  • 使用C++ 14,您可以进一步使用constexpr模板变量.这允许您为模板化函数添加别名:

    template<typename T>
    constexpr void old_function(/* args */);
    
    template<typename T>
    constexpr auto alias_to_old = old_function<T>;
    
    Run Code Online (Sandbox Code Playgroud)
  • 此外,从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);
    
    Run Code Online (Sandbox Code Playgroud)

  • `constexpr`模板变量方法似乎存在问题:别名不能进行类型推导.编译器要求我提供模板参数列表(我正在编写一个可变参数模板函数):如果没有模板参数列表,则无法引用变量模板`alias_to_old' (6认同)

Bri*_*ndy 34

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

void fn()
{
}

//...

void (*p)() = fn;//function pointer
void (&r)() = fn;//function reference
Run Code Online (Sandbox Code Playgroud)

  • 这需要蛋糕.我不知道函数引用. (2认同)

jer*_*jer 21

typedef int (*printf_alias)(const char*, ...);
printf_alias holler = std::printf;
Run Code Online (Sandbox Code Playgroud)

你应该没事吗?

  • 如果你包含<stdio.h>,它是全局的,但如果你包括<cddio>,则在std中 (3认同)

MSa*_*ers 10

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


Ant*_*all 8

使用 C++14 泛型 lambda,我能够执行以下操作,当目标函数具有多个重载时,这也应该起作用:

constexpr auto holler = [] ( auto &&...args ) {
        return printf( std::forward<decltype(args)>( args )... );
    };
Run Code Online (Sandbox Code Playgroud)


小智 7

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


sai*_*009 6

来自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)...); \
}
Run Code Online (Sandbox Code Playgroud)


Kev*_*son 5

在这里值得一提的是,虽然最初的问题(和很好的答案)如果你想重命名一个函数(有充分的理由这样做!)绝对有用,但如果你想做的只是去掉一个深层的命名空间,但是保留名称,有一个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
}
Run Code Online (Sandbox Code Playgroud)

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

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