能否在运行时重载一个函数?

5

我希望简化一段代码,其中大约有100个类似这样的表达式:

if( flag )
    AddData( key, some_number );
else
    AddData( key, error_description );

其中AddData被重载为

bool AddData( int key, double value );
bool AddData( int key, const char * error );

我希望将上面的代码表达为以下形式:
AddData( key, flag? some_number : error_description );

当然,这段代码无法编译,因为标志的值是在运行时确定的,而AddData签名需要在编译时确定。
将这两个函数合并成类似以下的东西:
bool AddData( int key, bool flag, double value, const char * error );

解决哪些参数使用哪些参数不使用的问题并能够正常运行,虽然可行,但看起来并不美观。

因此问题来了:有没有更合理的方法在运行时解决函数重载的问题?


AddData(key, flag ? some_number : error_description); 看起来类似于 AddData(key, flag, some_number, error_description);... - Jarod42
1
只评估 someNumber/errorDescription 中的一个是否很重要?此外,标志在每次调用时是否为不同的表达式? - Deduplicator
你可以使用函数指针。根据输入,解引用相应的函数指针。 - Thomas Matthews
那么,每个块的标志都不同,密钥也是如此,而且一些数字和错误描述都必须计算?如果不需要这样做,那么这样做是否昂贵/具有破坏性? - Deduplicator
可以使用变参函数,但我肯定不会推荐这样做。类型安全是有原因的。bool AddData(int key, bool flag, ...) - indiv
显示剩余2条评论
3个回答

2
只需要在函数中定义一个小助手,然后使用它即可:
auto AddHelper = [](bool flag, int key, double value, const char* error) {
    return flag ? AddData(key, value) : AddData(key, error);
}

如果标志始终相同,那么这是一个简单的更改:

auto AddHelper = [flag](int key, double value, const char* error) {
    return flag ? AddData(key, value) : AddData(key, error);
}

依赖编译器进行优化。

第二个版本更好(我打赌flag在父函数的生命周期内是常量)。它足够简短并且意图正确。 - Mark Lakata

1
你最好使用多态而不是数百个if语句。
不要使用标志,而是使用一个具有数据添加功能的多态基类,并选择正确的派生类,而不是更改标志。
然后,调用代码将简单地为:
data_adder->add(key, value, error_description);

示例基类和派生类:

struct DataAdder {
  virtual void add(int key, double value, const char *error) = 0;
 protected:
  ~DataAdder(){};
};

struct ValueDataAdder : DataAdder {
  void add(int key, double value, const char*) override { AddData(key, value); }
};

struct ErrorDataAdder : DataAdder {
  void add(int key, double, const char* error) override { AddData(key, error); }
};

实时演示


0
假设无法将问题中的表达式中的任何符号分解出来,那么最好的结果就是:
AddData(key, flag, some_number, error_description)

如果您可以将其分解为可能适用于多个调用的flag,那么您可以开始使用类似以下结构的更好的方法:
Adder<flag>{}
  .AddData(key1, val1, error1)
  .AddData(key2, val2, error2)
  .AddData(...)
  .
  .

即一个“流畅”的接口,每次记住哪一边的if被执行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接