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;