在虚拟方法中推断'this'的类型名

时间:2019-03-15 09:04:33

标签: c++11 templates

我知道C ++中缺少反射和基本模板机制,因此下面的示例无法正常工作。但是也许会有黑客以另一种方式实现预定目的?

postgres=# select to_json(now() at time zone 'America/New_York') NYC,
postgres-# to_json(now() at time zone 'Asia/Bangkok') Bangkok;
           nyc                |           bangkok         
------------------------------+------------------------------
 "2019-03-15T04:41:07.789954" | "2019-03-15T15:41:07.789954"

在示例中,template <typename OwnerClass> struct Template { OwnerClass *owner; }; struct Base { virtual void funct () { Template <decltype(*this)> temp; // ... } }; struct Derived : public Base { void whatever () { // supposed to infer this class and use Template<Derived> // any chance some macro or constexpr magic could help? funct(); } }; 调用虚拟方法Derived::whatever(),并希望其将其自己的类名(派生)传递给模板。编译器抱怨“ Base::funct()”。 'owner' declared as a pointer to a reference of type 'Base &'不仅不提供类型名,而且不提供引用,编译器还无法事先知道从 Derived 调用了funct,这将需要制作decltype(*this)模板。

但是,如果funct()是模板,则每个派生类在每次调用时都需要传递自己的名称,这是非常冗长和多余的。

是否有黑客可以解决此限制,并通过调用funct()来推断调用类的类型名称?也许funct()constexpr可以帮助编译器推断正确的类型并减少派生类中的冗长性?

2 个答案:

答案 0 :(得分:1)

当前无法完成。 BaseBase,实例化Template <decltype(*this)>时没有其他内容。您正在尝试将静态类型系统用于继承层次结构,该继承层次结构在运行时之前是无法解析的。这种完全相同的机制是在构造对象时不调用对象的virtual成员函数的原因。

在将来,此限制可能会更改。 Deducing this proposal展示了实现这一目标的第一步。

答案 1 :(得分:1)

您应该使用CRTP模式(奇怪的重复模板模式)进行继承。

定义基类:

struct CBase {
    virtual ~CBase() {}
    virtual void function() = 0;
};

定义一个准备好的CRTP类:

template<typename T>
struct CBaseCrtp : public CBase {
    virtual ~CBaseCrtp() {}

    void function() override {
        using DerivedType = T;
        //do stuff
    }
};

从CRTP继承一个:

struct Derived : public CBaseCrtp<Derived> {

};

应该可以。知道Derived类型的唯一方法是将其赋予基数!