如何使用其他函数的返回值调用重载函数

How to call overloaded function using return value from other function

本文关键字:函数 返回值 值调用 重载 返回 何使用 其他      更新时间:2023-10-16

我有以下类层次结构:

    选项(摘要(            ^            |     +------+-------+     |             |     +              + 某物[T]什么都没有

实现如下:

class Option {
public:
    Option() {};
    virtual ~Option() {};
    virtual bool nothing() = 0;
};
template <typename T>
class Something : public Option
{
public:
    Something(T _value) : value(_value) {};
    virtual ~Something() {};
    const T value;
    virtual bool nothing() {return false;};
};
class Nothing : public Option
{
public:
    Nothing() {};
    virtual ~Nothing() {};
    virtual bool nothing() {return true;};
};

现在,我希望能够编写具有以下签名的函数:

is_nothing: Nothing& => True
is_nothing: Something[T]& => False

我尝试通过以下方式使用模板:

template <class T> bool is_nothing(Nothing&) {return true;};
template <class T> bool is_nothing(Something<T> &) {return false;};

当像这样使用时,它确实有效:

is_nothing<int>(Nothing());
is_nothing<int>(Something<int>(4));

但是由于缺少is_nothing: Option& => bool而不想编译,当像这样调用时 is_nothing<int>(an_option())an_option: void => Option&实际返回Nothing的实例。所以对我来说,它似乎突然失去了进行多态调用的能力。

使用Option的代码:

Nothing n;
Option& an_option() {return n;};
int main(int argc,char** argv) 
{
    is_nothing<int>(an_option());
    return 0;
}

请引导我走向正确的方向,因为我觉得这种方法有些不对劲,但我不能完全理解它。

重载解析是根据参数的静态类型而不是动态(运行时(类型完成的。调用 is_nothing<int>(an_option()) 时,编译器会an_option()解析为返回 Option& 的函数,并将尝试根据该类型而不是引用绑定的对象的类型进行解析。

如果你解释了你想要解决的问题,你可能会得到一些在语言中工作的替代设计。最简单的通用方法,但同时也是一种被认为是代码异味且我不推荐的方法,是使用 RTTI 信息来推断实际类型。特别是,is_nothing的实现可以参考Option并使用RTTI(dynamic_casttypeid(来确定对象的动态类型是什么并相应地采取行动。

但这是一个糟糕的设计,如果你解释在什么情况下你需要这个以及你真正想要解决什么,你会得到更好的选择。

你不需要两个单独的函数。 Option有一个虚拟nothing()方法,因此您可以创建一个非模板函数来返回nothing()返回的任何内容:

bool is_nothing(Option& opt) { return opt.nothing(); }
Nothing n;
Option& an_option() { return n; }
int main(int argc,char** argv) 
{
    if (is_nothing(an_option()))
        ...
    return 0;
}

当然,当您可以直接调用nothing()时,这是多余的:

Nothing n;
Option& an_option() { return n; }
int main(int argc,char** argv) 
{
    if (an_option().nothing())
        ...
    return 0;
}