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

发布于 2024-09-05 12:34:53 字数 357 浏览 2 评论 0原文

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

解决方案:

  1. #define holler printf
  2. void (*p)() = fn; //函数指针
  3. void (&r)() = fn; //函数引用
  4. inline void g(){ f(); }

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 holler for printf. #define is obvious... any other way?

Solutions:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

古镇旧梦 2024-09-12 12:34:53

有不同的方法:

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

    const auto&新的_fn_名称 = 旧的_fn_名称;
    
  • 如果此函数有多个重载,您应该使用 static_cast

    const auto& new_fn_name = static_cast(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(std::stoi);
    

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

  • 使用 C++14,您可以使用 constexpr 模板变量走得更远。这允许您为模板函数添加别名:

    模板<类型名称 T>
    constexpr void old_function(/* args */);
    
    模板<类型名称 T>
    constexpr auto alias_to_old = old_function;
    
  • 此外,从 C++11 开始,您有一个名为 std::mem_fn 的函数,它允许为成员函数添加别名。请参阅以下示例:

    <前><代码>结构A {
    无效 f(int i) {
    std::cout << “论证:” <<我<< '\n';
    }
    };

    一个一个;

    自动问候 = std::mem_fn(&A::f); // 成员函数的别名
    // 打印“参数:5”
    问候(a,5); // 每次使用此别名时都应该提供一个对象

    // 如果你想永久绑定一个对象,请使用 `std::bind`
    greet_a = std::bind(greet, a, std::占位符::_1);
    问候_a(3); // 等价于greet(a, 3) => AF(3);

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 constexpr template 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_fn that 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);
    
蝶舞 2024-09-12 12:34:53

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

void fn()
{
}

//...

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

You can create a function pointer or a function reference:

void fn()
{
}

//...

void (*p)() = fn;//function pointer
void (&r)() = fn;//function reference
你的往事 2024-09-12 12:34:53
typedef int (*printf_alias)(const char*, ...);
printf_alias holler = std::printf;

你应该没问题。

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

Should do you fine.

简单 2024-09-12 12:34:53

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

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

何必那么矫情 2024-09-12 12:34:53

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

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

With C++14 generic lambdas, I was able to do the following, which should also work when the target function has multiple overloads:

constexpr auto holler = [] ( auto &&...args ) {
        return printf( std::forward<decltype(args)>( args )... );
    };
素罗衫 2024-09-12 12:34:53

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

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

獨角戲 2024-09-12 12:34:53

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

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)...); \
}
谁把谁当真 2024-09-12 12:34:53

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

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

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

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 using keyword for this:

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 cout and endl so I don't need to bring in ALL of std with 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.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文