模板化(或以某种方式自动)方法的返回值

时间:2011-10-12 02:50:29

标签: c++ templates inheritance c++11

编辑:要明确 - 立即 - 这是一个关于现代C ++编译器的语言能力的问题。不是关于具体目标的问题。如果不先澄清这个概念就很难描述这样一个抽象的概念而且我已经意识到一些混乱围绕着通常做的而不是可能做的事情。这是一个非常抽象的问题。这里没有任何东西可以编译,这是故意的。同样地,我不是在问这个具体案例是如何工作的,但是我想问是否有办法让C ++认识到我想做什么(通过模板化或某种类型的auto-> decltype技巧最有可能如果可能的话。)

我不是C ++的新手,但肯定不是专家。这是我一直在努力解决的根本问题,因为我重新发现了语言的力量。这里的最终目标是优雅地(并且尽可能少地使用代码)基于调用上下文转发适当的多态返回值。例如......

class A {
    public:
        A& foo() {
            // do something mutant fooish
            return *this;
        };
};

class B: public A {
    public:
        B& bar() {
            // do something mutant barish
            return *this;
        };
};

int main(int argc, char** argv) {
    B yarp;
    yarp.foo().bar();
};

编译错误。有道理,C ++旨在假设你对你正在做的事情一无所知(这使得它高度可以优化但有时很痛苦......一种高级别的中级OOP语言)。

Obvioiusly C ++编译器已经达到了这样的程度:他们不仅知道你要求的东西(A()。foo()是否正常工作而B()。foo()工作方案),还有什么你要求它的上下文(因此在C ++ 11中自动yarp = B(),编译器知道yarp是B的一个实例)。有没有办法优雅地利用它,而不必重现一堆“使用”语句或包装方法(根据gcc二进制文件的反汇编,奇怪的是没有得到优化)?

这里有诀窍吗?我根本没有在网上学到的东西。一个自动 - > decltype技巧或模板技巧?例如:

class A {
    public:
        template <typename R>
        R& foo() {
            // do something fooish
            return (R&)*this;
        };
};

class B: public A {
    public:
        using A::foo<A>; // << even this would be better than nothing (but no where near  optimum)
        B& bar() {
            // do something barish
            return *this;
        };
};

更简单的东西?如果将此概念扩展到用于引用计数和gc释放的代理模板类的运算符,则很明显这会产生什么问题。提前感谢您的任何帮助(哦,首先发布stackoverflow,所以如果我有任何格式错误或者你有更好的结构化帖子的建议,请为此道歉并请指出它们。)

3 个答案:

答案 0 :(得分:2)

显而易见的解决方案是将其分成两行:

yarp.foo();
yarp.bar();

或者,使用static_cast来获取对B&amp;的引用,所以

static_cast<B&>(yarp.foo()).bar();

同意,这有点冗长,但是在一行中将多个成员函数调用链接在一起,就像这对C ++来说是非常不寻常的语法。它只是没有出现很多,所以语言不能很好地支持这个成语。我从未遇到过遇到这个问题的情况。

如果你想设计一些可链接的功能,你可以使用其他更好的习语。一个例子是Boost的范围适配器,它使运算符重载实现链接。

编辑:另一种选择是在B&amp;:

中重载foo()
class B: public A {
    public:
        B& foo() { A::foo(); return *this; }

        B& bar() {
            // do something mutant barish
            return *this;
        };
};

答案 1 :(得分:2)

我认为没有自动类型检测,因为编译器甚至不知道哪些类将继承A

在第二次试用中,C ++禁止using模板专业化。所以这不会编译。

我认为您可以尝试的另一个技巧是使A成为模板

template <typename FinalType>
class A {
    public:
        FinalType& foo() {
            // do something fooish
            return static_cast<FinalType&>(*this);
        };
};

class B: public A<B> {
    public:
        B& bar() {
            // do something barish
            return *this;
        };
};

答案 2 :(得分:0)

嗯,你声明了一个没有方法foo的B类实例 - 所以难怪有编译错误 - 你的意思是     。yarp.bar()FOO();