c++ - 如何派生出需要嵌套类模板类型的模板类?

标签 c++ c++11

我正在使用 OpenGL (C API) 并将一些东西封装在类中。基本上,调用 glGenX 会生成 GLuint,它们是实际创建的对象的句柄。当您清理时,您应该对这些句柄调用 glDeleteX

这意味着,对我来说,拥有一个类来保存这些(以及封装一些其他特定于它们的东西)并能够复制实例并传递它们,该类需要内部引用计数,以便它仅在没有更多引用时调用 glDeleteX

我现在已经完成了两次,我正在考虑第三堂课。我可以看到我正在制作的很多类(class)都需要这个;所以我想使用模板来简化它。

下面是原始类的示例,其引用计数仅在适当的时间调用 glDeleteX:

class Texture
{
public:
    Texture(const GLuint texture) : m_data(new Data(texture)) {}
    Texture(const Texture& t) : m_data(t.m_data) { ++m_data->m_count; }
    Texture(Texture&& t) : m_data(t.m_data) { ++m_data->m_count; }
    ~Texture() { if(--m_data->m_count == 0) delete m_data; }

    void Bind(GLenum target, GLint location) const { /* do some stuff */;
    void Release() const { /* do some stuff */

    GLuint GetTexture() const { return m_data->m_texture; }

private:

    class Data
    {
    public:
        Data(const GLuint texture) : m_count(1), m_texture(texture) {}
        Data(const Data& data) : m_count(1), m_texture(data.m_texture) {}
        ~Data() { glDeleteTexture(1,&m_texture); }

        GLuint m_texture;
        unsigned int m_count;
    };

    Data* m_data;
};

这是我对其进行模板化的尝试:

template<typename... Ts>
class ReferenceCountedObject
{
public:

    ReferenceCountedObject(const Ts... args)
    :
        m_data(new Data(args...))
    {}

    ReferenceCountedObject(const ReferenceCountedObject& h)
    :
        m_data(h.m_data)
    {
        ++m_data->m_count;
    }

    ReferenceCountedObject(ReferenceCountedObject&& h)
    :
        m_data(h.m_data)
    {
        ++m_data->m_count;
    }

    virtual ~ReferenceCountedObject()
    {
        if(--m_data->m_count == 0)
            delete m_data;
    }

protected:

    class Data
    {
    public:

        Data(const Ts... args)
        :
            m_count(1),
            m_dataMembers(args...)
        {
        }

        Data(const Data& data)
        :
            m_count(1),
            m_dataMembers(data.m_dataMembers)
        {
        }

        virtual ~Data()
        {
            std::cout << "deleting base" << std::cout;
        }

        std::tuple<Ts...> m_dataMembers;
        unsigned int m_count;
    };

    Data* m_data;
};

想法是,内部Data类可能只需要一个GLuint句柄来处理Texture类,但它可能需要三个不同的句柄来处理另一个类型。所以,这就是内部 tuple 的原因。

现在,我遇到了问题。这是我现在派生自这个模板化类的原始类:

class Texture : public ReferenceCountedObject<GLuint>
{
public:
    Texture(GLuint texture) : ReferenceCountedObject(texture) {}

    Texture(const Texture& t) : ReferenceCountedObject(t) {}

    Texture(Texture&& t) : ReferenceCountedObject(t) {}

    void Bind(GLenum target, GLint location) const { /* does that stuff */}
    void Release() const { /* does that stuff */ }

    GLuint GetTexture() const { return std::get<0>(m_data->m_dataMembers); }

protected:
};

如何定义基类 Data 的析构函数?到目前为止,我试过这样做:

稍微改变一下基类:

template<class DataType, typename... Ts>
class ReferenceCountedObject
{
    /* ... */
protected:
    DataType* m_data;
};

因此您可以通过这种方式提供数据类型并覆盖虚拟析构函数:

class Texture : public ReferenceCountedObject<Texture::TData,GLuint>
{
    /* ... */
protected:
    class TData : public ReferenceCountedObject::Data
    {
    public:
        ~TData()
        {
            std::cout << "deleting derived" << std::cout;
            glDeleteTextures(1,&std::get<0>(m_dataMembers));
        };
    };
}

但我无法使用 Texture::TData 实例化 ReferenceCountedObject,因为 TData 是我要定义的内容的一部分。

我怎样才能正确地做到这一点?我承认我可能会以完全错误的方式解决这个问题。

最佳答案

为什么不直接使用shared_ptr?这也是引用计数,传递起来更简单。你的类只需要处理分配和释放纹理,shared_ptr 在正确的时间进行引用计数和自动删除。另外,这让你可以免费使用弱指针。

你可以定义你的内部纹理类,然后做

typedef std::shared_ptr<internal::Texture> Texture;

这样外部用户只能使用引用计数的纹理。

关于c++ - 如何派生出需要嵌套类模板类型的模板类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31063013/

相关文章:

c++ - 具有已删除方法的 C++ 类是否可以轻松复制?

C++ move 语义(和右值引用)与普通引用

c++ - 匹配继承的成员函数的类型

c++ - 粉刺 : Avoiding pointer to pointer with pimpl

c++ - 模板外部(与外部模板相比)

C++ 11 - 右值引用变量

c++ - mcrypt linux 如何使用 rijndael 256 cbc

javascript - 如何使用 v8 native 插件将 C++ 数组传送到 node.js

python - 将 Python 添加到 C++ : not finding Python. h

c++ - "struct atomic"的复制构造函数