2

对于某些语法糖,我想返回对 的引用this,但是在继承时,该函数应返回子类的类型:

class base {
  T &operator!() { return *this; }
};
base b; b = !b;

class child : public base {};
child c; c = !c;

由于操作员,我不能只返回指针和 dynamic_cast 它,它必须是一个引用。

这甚至可能吗?使用decltype(*this)for T 不起作用,也不起作用auto f()->decltype(*this),因为this(虽然我不明白为什么,在自动情况下)

在 Scala 中,您可以编写如下内容:

template<typename T> class base {
  T &f() { return *this; }
};
class child : public base<child> {};

但是我的 g++ 不会接受这个(不确定这是错误还是不在规范中?)

当然有明确的方式,但我想知道是否可以使用 C++11 特性来避免这种情况?

class child : public base {
  child &operator!() { base::operator!(); return *this }
};
4

2 回答 2

2

如果允许您制作base模板,您可以使用 CRTP 执行此操作:

template <typename Derived> class Base {
protected:
    Derived& refToThis() {
        return *static_cast<Derived*>(this);
    }
};

注意这里的额外演员。这样做的原因是,如果您有这样的课程:

class Subclass: public Base<Subclass> {
    /* ... */
};

然后,如果您refToThis从该类内部调用,它将调用基类版本。由于类继承自Base<Subclass>,因此实例化的模板refToThis将是

    Subclass& refToThis() {
        return *static_cast<Subclass*>(this);
    }

这段代码是安全的,因为this指针确实指向一个Subclass对象。此外,static_cast如果派生类没有Base正确继承,则将确保转换在编译时失败,因为指针类型不可转换。

这里需要演员表的原因是,如果你只是说

template <typename Derived> class Base {
protected:
    Derived& refToThis() {
        return *this;
    }
};

然后程序中有一个类型错误,因为 aBase本身不是a Derived,如果你可以在没有任何检查的情况下将 a 转换Base&为 a ,你可能会破坏类型系统。Derived&

那就是说......我根本不会这样做。operator!为此目的重载会降低代码的可读性,而仅仅编写代码*this是如此地道,以至于隐藏它会使您的代码更难理解。使用所有这些模板机制来避免常见的 C++ 似乎是错误的。如果您在返回引用之前正在做其他事情,那很好,但这似乎不是一个好主意。

希望这可以帮助!

于 2012-02-13T17:49:08.693 回答
0

请不要这样做。已经有一种方法可以在语言中做到这一点,*whatever_pointer_you_want_to_use_this_crazy_operator_upon. 用这种语言创建一种新的做事方式只会让你未来的维护者感到困惑。你还有什么真正想要在这里实现的吗?

于 2012-02-13T18:21:38.977 回答