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

时间:2014-10-22 23:32:01

标签: c++ templates c++11 overloading

我有以下类层次结构:

     Option (abstract)
            ^
            |
     +------+-------+
     |              |
     +              +
 Something[T]    Nothing

实施如下:

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;
}

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

2 个答案:

答案 0 :(得分:0)

重载分辨率是根据参数的 static 类型完成的,而不是 dynamic (运行时)类型。当您调用is_nothing<int>(an_option())时,编译器会将an_option()解析为返回Option&的函数,并尝试根据该类型解析,而不是参考绑定的对象的类型。

如果您解释要解决的问题,可能会获得一些在该语言中有效的替代设计。最简单,通用的方法,但同时被认为是代码气味,我不建议使用RTTI信息来推断实际类型。特别是,is_nothing的实现可以引用Option并使用RTTI(dynamic_casttypeid)来确定对象的动态类型,并据此采取相应措施

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

答案 1 :(得分:0)

您不需要两个单独的功能。 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;
}