template 模板类,如果存在则调用函数

The*_*ist 4 c++ templates stl template-templates c++11

我有一个带有模板模板参数的简单函数。它的目的是采用一个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;
}
Run Code Online (Sandbox Code Playgroud)

这是类的静态成员函数SmartPtr<T>

你在这里看到的,这一切所做的就是将push_back所有元素从input_container另一个元素转移到另一个元素并返回。

您可能已经注意到,如果输入是std::vector,则插入会出现性能问题,而这对于和O(1)来说没问题。所以我想做的是在循环之前调用它(如果可能的话)(在编译时决定)std::liststd::deque

container.reserve(input_container.size());
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

ACB*_*ACB 5

检查类是否有保留功能:

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;
};
Run Code Online (Sandbox Code Playgroud)

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 { };
Run Code Online (Sandbox Code Playgroud)

如果可能的话调用保留的函数:

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)
{
}
Run Code Online (Sandbox Code Playgroud)

只需在循环之前调用 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;
}
Run Code Online (Sandbox Code Playgroud)

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; };
Run Code Online (Sandbox Code Playgroud)