不太清楚这里的标题怎么表达。
问题是我有一个类模板:
template<various parameters> struct Base { ... };然后,我有一组来自于它的开放的类:
struct A: public Base<some arguments> { ... };
struct B: public Base<other arguments> { ... };
struct C: public Base<different arguments> { ... };
...重要的是,派生类除了修复模板参数--非成员函数,尤其是成员变量之外,不会向基本库添加任何内容。所以它们的二进制表示都应该是相同的。我使用继承而不是类型防御的唯一原因是,我希望能够转发--声明A、B、C等(或者更准确地说,A、B、C等是由客户端使用提供的宏定义的,为了方便,我希望他们能够转发--声明)。拥有A、B、C等的根本原因是为了避免一直用手写出模板参数。
问题是Base有一些函数将回调作为参数,回调应该将对类本身的引用作为参数。
因此,我希望具有如下回调函数:
void foo (A&, ...);
void bar (B&, ...);以此类推。在Base中回调函数的实现中,我想将*作为回调的参数传递。非常明智的是,C++不允许我这样做,因为在预期派生类的地方传递基类通常不安全。但是在这种特殊的情况下,它不应该是一个问题,因为派生类不会给基添加任何东西,而只是被使用而不是类型防御。
看来我有三个标准:
它们是互不相容的。(第三个标准同样是为了方便客户端,因为每次手动将模板参数写入基类将是非常冗长的,而不想这样做是使用“typedefs”的全部原因。)
我认为有三种解决办法:
还有更好的吗?
(允许使用C++11。)
发布于 2011-11-17 22:22:36
使用CRTP成语并在模板参数中传递派生类。对于回调,只需将*this转换为派生类型即可。
template<class Derived, other params...>
struct Base{
template<class F>
void do_callback_stuff(F func){
func(static_cast<Derived&>(*this), ....);
}
};
struct A : public Base<A, other args...>{};发布于 2011-11-17 22:53:07
正如其他人所建议的那样,CRTP可以是一种解决办法。
但是,您还应该重新考虑回调何时以及为什么需要对对象的引用,而对象的专用调用方并不详细地了解它自己。我想说的是:“类模板在实例化之前并不了解它自己的详细信息”。
因此,检查回调可能具有的与调用者对象引用(实例化的类模板对象)相关的使用模式。并提取公共基类或基接口。
然后从该基派生类模板:
struct BaseInterface {
// HERE, declare anything, that callbacks may use
virtual void foo() = 0;
};
template<various parameters>
struct Base : public BaseInterface { ... };
void some_callback( BaseInterface& caller, ... );发布于 2011-11-17 22:33:10
也许将奇怪地反复出现的模板模式和隐式转换结合在一起就可以做到这一点:
template<typename Derived, various parameters> struct Base
{
operator Derived&() { return static_cast<Derived&>(*this); }
operator Derived const&() const { return static_cast<Derived const&>(*this); }
other stuff;
};
struct A: Base<A, some arguments> {};https://stackoverflow.com/questions/8175155
复制相似问题