我有一个带有模板template参数的简单函数。这意味着要使用STL容器,将智能ptr转换为普通ptr(这是C++ 03项目,但我也对C++ 11的答案感兴趣):
template <template <typename _T, typename = std::allocator<_T> > class Container>
static Container<T*> GetRawPtrContainer(const Container<SmartPtr<T> >& input_container)
{
Container<T*> container;
for(typename Container<SmartPtr<T> >::const_iterator it = input_container.begin();
it != input_container.end();
it++)
{
container.push_back(it->ptr);
}
return container;
}
这是
SmartPtr<T>
类的静态成员函数。您会在这里看到,所有这些都是
push_back
从input_container
到另一个元素的所有元素,然后返回。您可能已经注意到,如果输入的是
std::vector
,则O(1)
插入会出现性能问题,而std::list
和std::deque
很好。所以我想做的是如果可能(在编译时确定),请在循环之前调用它:container.reserve(input_container.size());
我怎样才能做到这一点?
最佳答案
检查类是否具有保留功能:
C++ 03:
template<typename T> struct HasReserve {
struct Fallback { void reserve(size_t); };
struct Derived : T, Fallback { };
template<typename C, C> struct Check;
template<typename C> static char(&f(Check<void (Fallback::*)(size_t), &C::reserve>*))[1];
template<typename C> static char(&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
C++ 11:
template <typename T, typename = int>
struct HasReserve : std::false_type { };
template <typename T>
struct HasReserve <T, decltype(&T::reserve, 0)> : std::true_type { };
如果可能,调用保留的函数:
template<typename T>
typename std::enable_if<HasReserve<T>::value>::type
Reserve(T& container, size_t s)
{
container.reserve(s);
}
template<typename T>
typename std::enable_if<!HasReserve<T>::value>::type
Reserve(T&, size_t)
{
}
只需在循环之前调用Reserve函数,它就可以像您希望的那样工作。
template <template <typename _T, typename = std::allocator<_T> > class Container>
static Container<T*> GetRawPtrContainer(const Container<SmartPtr<T> >& input_container)
{
Container<T*> container;
Reserve(container, input_container.size()); // just add this to your function
for(typename Container<SmartPtr<T> >::const_iterator it = input_container.begin();
it != input_container.end();
it++)
{
container.push_back(it->ptr);
}
return container;
}
C++ 03的std::enable_if
template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };