是否有可能有一个成员变量,它能够从指向自身的指针(在它的方法中)计算指向包含对象的指针?
让我们在 API 中封装一个外部调用接口,如下所示:
template <typename Class, MethodId Id, typename Signature>
class MethodProxy;
template <typename Class, MethodId Id, typename ReturnT, typename Arg1T>
class MethodProxy<Class, Id, ReturnT ()(Arg1T) {
public:
ReturnT operator()(Class &invocant, Arg1T arg1);
};
对于从 0 到 N 的其他数量的参数也是如此。对于外部的每个类,一个 C++ 类都声明了一些特征,并且此模板使用这些特征(以及参数类型的更多特征)来查找和调用外部方法。这可以像这样使用:
Foo foo;
MethodProxy<Foo, barId, void ()(int)> bar;
bar(foo, 5);
现在我想做的是以Foo
这样的方式定义,我可以这样称呼:
Foo foo;
foo.bar(5);
无需多次重复签名。(显然,创建一个静态成员并将调用包装在一个方法中很简单,对)。好吧,事实上,这仍然很容易:
template <typename Class, MethodId Id, typename Signature>
class MethodMember;
template <typename Class, MethodId Id, typename ReturnT, typename Arg1T>
class MethodMember<Class, Id, ReturnT ()(Arg1T) {
MethodProxy<Class, Id, Signature> method;
Class &owner;
public:
MethodMember(Class &owner) : owner(owner) {}
ReturnT operator()(Arg1T arg1) { return method(owner, arg1); }
};
然而,这意味着对象最终将包含许多指向自身的指针副本。所以我正在寻找一种方法来使这些实例能够计算所有者指针this
和一些额外的模板参数。
我在想
template <typename Class, size_t Offset, ...>
class Member {
Class *owner() {
return reinterpret_cast<Class *>(
reinterpret_cast<char *>(this) - Offset);
}
...
};
class Foo {
Member<Foo, offsetof(Foo, member), ...> member;
...
};
但这抱怨 Foo 在这一点上是不完整的类型。
是的,我知道offsetof
它应该只适用于“POD”类型,但实际上适用于任何非虚拟成员,这将是有效的。我同样尝试在该参数中传递指向(那个)成员的指针(使用虚拟基类),但这也不起作用。
请注意,如果这可行,它还可以用于实现类似 C# 的属性,委托给包含类的方法。
我知道如何使用 boost.preprocessor 执行上述包装方法,但参数列表必须以一种奇怪的形式指定。我知道如何编写宏以通过模板生成通用包装器,但这可能会导致诊断不佳。如果电话看起来像foo.bar()(5)
. 但我想知道一些聪明的技巧是否可能(加上只有这样的聪明技巧可能也可用于属性)。
注意:成员类型实际上不能专门用于指向它的成员指针或偏移量,因为在分配偏移量之前必须知道类型。这是因为类型会影响所需的对齐方式(考虑显式/部分专业化)。