【问题标题】:Overloading C++ functions without passing parameters重载 C++ 函数而不传递参数
【发布时间】:2013-07-13 08:16:43
【问题描述】:

是否可以在 C++ 中使用类似于函数参数的某种标识符来重载函数?这将允许更轻松地使用模板。它还可以使代码在我的特定情况下看起来更好,我没有详细解释。

如果这没有多大意义,而且老实说我什至不知道正确的关键字(请告诉我),这里有一个玩具示例:

我想写这样的东西

function(i);
function(special_action);
function(special_action_2);

这样理解

function(i);
function_special_action();
function_special_action_2();

实现这一目标的最佳方法是什么?到目前为止,我已经尝试过这样的虚拟枚举:

// normal action
void function(int i) { ... }

// special actions
enum dummy_enum_for_special_action { special_action };
void function(const dummy_enum_for_special_action & dummy) { ... }

我猜参数传递将被编译器优化掉。但是,有没有更好的方法来做到这一点?

【问题讨论】:

    标签: c++ function enums arguments identifier


    【解决方案1】:

    这被称为“tag dispatch”,它是提供通用函数的库(例如标准<algorithms> 库)的一种非常常见的技术。

    只需为参数使用单独的标签类型:

    struct i { }; // bad name.
    struct special_action { };
    struct special_action_2 { };
    

    函数声明:

    void function(i) { … }
    void function(special_action) { … }
    void function(special_action_2) { … }
    

    然后这样调用:

    function(i());
    function(special_action());
    function(special_action_2());
    

    或者,如果您想去掉括号,请使用全局实例(但我不确定这是一个好主意);

    namespace { // See comment below
        struct i_t { } i;
        // etc …
    }
    
    void function(i_t) { … }
    // etc …
    

    unnamed namespace 是必要的,以避免在全局范围内声明的变量名违反 one definition rule

    【讨论】:

    • static struct i_t {} i; 效果更好。哦,另一种方法是 function<special_action>(),您可以在其中 template 专门化该函数,然后让它在专门化中使用它想要的任何调度机制。
    • @Yakk 这种方式不是被弃用了吗? (不是正式的,但在使用中。编辑:正式!§7.3.1.1/2)但是确实,我需要 some 机制来满足 ODR,所以要么static 要么匿名命名空间。
    【解决方案2】:

    您可以使用一系列虚拟类型来实现“tagging”的不同功能。这是一个例子

    #include <iostream>
    
    using namespace std;
    
    template <typename tag>
    void func(const tag&);
    
    struct First{};
    First first;
    
    template <>
    void func(const First&){
        cout << "funcFirst" << endl;
    }
    
    struct Second{};
    Second second;
    
    template <>
    void func(const Second&){
        cout << "funcSecond" << endl;
    }
    
    struct Third{};
    Third third;
    
    void func(const Third&){
        cout << "funcThird" << endl;
    }
    
    int main()
    {
        func(first);
        func(second);
        func(third);
    }
    

    你可以试试here

    当然,我建议您使用适当的命名空间,以避免此类全局定义出现问题,尤其是涉及“第一”和“第二”的问题(在我的示例中)。

    请注意,您甚至不需要将函数设为模板,这只是一种可能性。您可以依赖简单的重载,如 func(const Third&)。

    【讨论】:

      猜你喜欢
      • 2018-09-25
      • 2021-03-10
      • 1970-01-01
      • 1970-01-01
      • 2019-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多