C++ 嵌套在模板化类中但不依赖于模板参数的类的大小

C++ 嵌套在模板化类中但不依赖于模板参数的类的大小,c++,templates,sizeof,C++,Templates,Sizeof,我有以下代码: template < unsigned int Num, class ValueType > class COuter { public: class CInner { private: CInner* m_pPrev; CInner* m_pNext; ValueType* m_pValue; } } 不必为COuter指定模板参数 谢谢 如果使用这些

我有以下代码:

template < unsigned int Num, class ValueType >

class COuter
{

    public:     
    class CInner
    {

        private:
        CInner* m_pPrev;
        CInner* m_pNext;
        ValueType*  m_pValue;
    }
}
不必为COuter指定模板参数


谢谢

如果使用这些指针时的类型安全是您主要关心的问题,那么您可以这样做:

class CInnerBase
{
    protected:
    void* m_pPrev;
    void* m_pNext;
    void* m_pValue;
};

template <unsigned int Num, class ValueType>
class COuter
{
    public:     
    class CInner : public CInnerBase
    {
        public:
        ValueType* pValue() { return static_cast<ValueType*>(m_pValue); }
        //and similar for m_pPrev and m_pNext
        //also type-safe constructors and assignment operators
    };
};
classcinnerbase
{
受保护的:
void*m_pPrev;
void*m_pNext;
void*m_p值;
};
模板
班长
{
公众:
类CInner:公共CInnerBase
{
公众:
ValueType*pValue(){返回静态_转换(m_pValue);}
//m_pPrev和m_pNext的情况类似
//还可以键入安全构造函数和赋值运算符
};
};
然后,您的分配器就可以使用
CInnerBase
COuter
可以将它从分配器获得的内容转换为相应的
CInner*
类型

CInnerBase
可以是分配器类的内部类

您可能会发现,一些不依赖于这些模板参数的功能将自然地从模板
CInner
迁移到非模板
CInnerBase
——这对于避免代码膨胀来说是不错的


另外,
m_-pPrev
m_-pNext
可以是
CInnerBase*
,如果这样有帮助的话。

您想从同一内存池中分配两个或多个布局相同但类型不同的对象

假设您使用的内存池类模板与此模板类似:

然后,您可以使用以下分配和解除分配功能,这些功能使用placement new将POD存储类型转换为所需类型

#include <new>

template<typename T>
T* allocate(Pool& pool)
{
    static_assert(sizeof(T) == sizeof(Storage));
    static_assert(alignof(T) == alignof(Storage));
    return new (pool.allocate()) T();
}

template<typename T>
void deallocate(Pool& pool, T* p)
{
    static_assert(sizeof(T) == sizeof(Storage));
    static_assert(alignof(T) == alignof(Storage));
    p->~T();
    pool.deallocate(reinterpret_cast<Storage*>(p));
}

int main()
{
    Pool pool;
    typedef COuter<0, int>::CInner Type;
    Type* p = allocate<Type>(pool);
    deallocate(pool, p);
}

使CInner成为COuter的子类虽然可能没有帮助,但看起来确实更好“
CInner的大小显然不取决于COuter的模板参数”
ValueType*m_pValue
行看起来可疑。它是一个指针,所以m_pValue的大小并不取决于ValueType,我能想到的唯一一件事是,如果您将
m_pValue
设置为
void*
类型,并在每次使用时将其转换为实际类型。是的,如果您参考
COuter
模板参数列表,它就是一个指针。但是如果你独自离开辛纳,那意味着什么呢?在这种情况下,编译器如何推断出您的想法。
template<typename T>
struct memory_pool
{
    T* allocate();
    void deallocate(T*);
};
typedef COuter<0, void>::CInner Storage;
typedef memory_pool<Storage> Pool;
#include <new>

template<typename T>
T* allocate(Pool& pool)
{
    static_assert(sizeof(T) == sizeof(Storage));
    static_assert(alignof(T) == alignof(Storage));
    return new (pool.allocate()) T();
}

template<typename T>
void deallocate(Pool& pool, T* p)
{
    static_assert(sizeof(T) == sizeof(Storage));
    static_assert(alignof(T) == alignof(Storage));
    p->~T();
    pool.deallocate(reinterpret_cast<Storage*>(p));
}

int main()
{
    Pool pool;
    typedef COuter<0, int>::CInner Type;
    Type* p = allocate<Type>(pool);
    deallocate(pool, p);
}
#include <type_traits> 

typedef COuter<0, void>::CInner VoidInner;
const std::size_t SIZE = sizeof(VoidInner);
const std::size_t ALIGN = alignof(VoidInner);
typedef std::aligned_storage<SIZE, ALIGN>::type Storage;