C ++编译器无法识别模板化钻石

时间:2017-10-16 14:58:21

标签: c++ templates diamond-problem

由于我无法控制的情况,我需要创建以下菱形,以便安全地从不同的线程访问和控制公共基类中的数据。

template <class T>
class Base
{
public:
    void writeLockT();
    void writeUnlockT();
    void readLockT();
    void readUnlockT();

    T* writeInstance();
    const T* readInstance();

private:
    SomeBuffer<T> m_buffer;
};

template <class T>
class Derived1 : public Foo, virtual public Base<T>
{
};

template <class T>
class Derived2 : public Bar, virtual public Base<T>
{
};

struct MyData
{
    int x;
    int y;
    int z;
    std::string name;
};

class Final: public Derived1<MyData>, public Derived2<MyData>
{
};

类SomeBuffer是一个自定义容器,它在3个T实例之间旋转,这样我就可以编写1个实例,而不会阻止访问那些想要读取的实例(它们获得最近编写的T版本,但不是当前的版本被写入。)

Foo和Bar都是接口(即:只有纯虚方法的类)。

这些类的实例存储为Foo指针或Bar指针,但从不作为Base或DerivedX指针存储(因为模板在代码中的那一点未知)。

如果Derived1和Derived2都采用相同的类作为模板参数,这看起来像死亡的正常钻石,但我注意到以下行为:

Base的构造函数被调用两次(我已经通过在Base的构造函数中放置&#34; cout&lt;&lt; this&lt;&lt; std :: endl&#34;&#34;来测试它了这个&#39;的价值每次都不同);

如果我在基类中调用一个方法,那么任何人都会猜测调用哪个基类(以与前一点相同的方式进行测试),这意味着如果我在一个点调用writeLockT而writeInstance在不同的位置调用点,我可以访问SomeBuffer的不同实例(破坏代码)。

请注意,锁定和解锁方法是通过Foo和Bar中的虚拟方法间接调用的(在Derived1和Derived2中过载),而实例方法则从Final内部调用。

为什么这不起作用?应该只有一个具有虚拟继承的Base实例,但我有2个。

为了记录,我的IDE是用于OpenSuse的KDevelop4,并且更改不是一个选项(我正在工作)。

感谢能帮助我的人。

0 个答案:

没有答案