我可以在 C 中实现自主的“自我”成员类型吗?

新手上路,请多包涵

C++ 缺少 PHP 的 self 关键字 的等效项,它计算为封闭类的类型。

在每个班级的基础上伪造它很容易:

 struct Foo
{
   typedef Foo self;
};

但我不得不再次写 Foo 。也许有一天我会弄错这个并导致一个无声的错误。

我可以使用 decltype 和朋友的某种组合来“自主”完成这项工作吗? 我已经尝试了以下 方法,但是 this 在那个地方无效:

 struct Foo
{
   typedef decltype(*this) self;
};

// main.cpp:3:22: error: invalid use of 'this' at top level
//     typedef decltype(*this) self;

(我不会担心 static 的等价物,它的作用相同,但具有后期绑定。)

原文由 Lightness Races in Orbit 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 257
2 个回答

以下是您可以在不重复 Foo 类型的情况下执行此操作的方法:

 template <typename...Ts>
class Self;

template <typename X, typename...Ts>
class Self<X,Ts...> : public Ts...
{
protected:
    typedef X self;
};

#define WITH_SELF(X) X : public Self<X>
#define WITH_SELF_DERIVED(X,...) X : public Self<X,__VA_ARGS__>

class WITH_SELF(Foo)
{
    void test()
    {
        self foo;
    }
};

如果要从 Foo 派生,则应按以下方式使用宏 WITH_SELF_DERIVED

 class WITH_SELF_DERIVED(Bar,Foo)
{
    /* ... */
};

您甚至可以使用任意数量的基类进行多重继承(感谢可变参数模板和可变参数宏):

 class WITH_SELF(Foo2)
{
    /* ... */
};

class WITH_SELF_DERIVED(Bar2,Foo,Foo2)
{
    /* ... */
};

我已经验证了它可以在 gcc 4.8 和 clang 3.4 上工作。

原文由 Ralph Tandetzky 发布,翻译遵循 CC BY-SA 3.0 许可协议

一种可能的解决方法(因为您仍然必须编写一次类型):

 template<typename T>
struct Self
{
protected:
    typedef T self;
};

struct Foo : public Self<Foo>
{
    void test()
    {
        self obj;
    }
};

对于更安全的版本,我们可以保证 T 实际上派生自 Self<T>

 Self()
{
    static_assert(std::is_base_of<Self<T>, T>::value, "Wrong type passed to Self");
}

请注意,成员函数中的 static_assert 可能是唯一的检查方法,因为传递给 std::is_base_of 的类型必须是完整的。

原文由 Sebastian Hoffmann 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题