2017-04-10 123 views
1

我有一个模板模板参数这个简单的函数。这意味着要采取一个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>的静态成员函数。

您在这里看到的所有这一切都是从input_containerinput_container的所有元素都返回。

您可能已经注意到,如果输入std::vector,那么就用O(1)插入性能问题,而这是罚款std::liststd::deque。所以我想要做的就是调用这个循环之前,如果有可能(在编译时决定)

container.reserve(input_container.size()); 

我怎么能这样做?

回答

1

检查类具有储备功能:

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; 
} 

的std :: enable_if为C++ 03

template<bool B, class T = void> 
struct enable_if {}; 

template<class T> 
struct enable_if<true, T> { typedef T type; }; 
+0

对不起,你可以展示一个例子,其中的C + + 03的例子会为我提出的问题工作? –

+0

就像这样:https://pastebin.com/c4NARK3e – ACB

+0

你可以添加到答案?我公司的防火墙阻止了pastebin。 –

1

您可以使用重载

// Common code in general template and specialization 
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; 
} 

// General template 
template <template <typename _T, typename = std::allocator<_T> > class Container> 
static Container<T*> GetRawPtrContainer(const Container<SmartPtr<T> >& input_container) 
{ 
    Container<T*> container; 
    return GetRawPtrContainer(input_container,container); 
} 

//Vector specialization 
template <template <typename _T> 
static Container<T*> GetRawPtrContainer(const std::vector<SmartPtr<T> >& input_container) 
{ 
    std::vector<T*> container; 
    container.reserve(input_container.size()); 
    return GetRawPtrContainer(input_container,container); 
} 
+0

@ W.F。这是真的,我会编辑:) – amchacon

0

这里是一个C++ 11的实现,是容器无关,储量情况下缓冲输入容器具有.reserve成员函数。

template<typename Container, typename T> 
auto 
insert(Container& container, T &&v, int) -> 
decltype(container.push_back(std::forward<T>(v)), void()) { 
    container.push_back(std::forward<T>(v)); 
} 

template<typename Container, typename T> 
void 
insert(Container &container, T &&v, ...) { 
    container.insert(std::forward<T>(v)); 
} 

template<typename T, template<typename...> class Container> 
auto 
GetRawPtrContainer_helper(Container<T> const &container, int) -> 
decltype(container.reserve(42), Container<typename T::element_type*>()) { 

    Container<typename T::element_type*> out; 
    out.reserve(container.size()); 
    for(auto &&e : container) insert(out, e.get(), 0); 

    return out; 
} 

template<typename T, template<typename...> class Container> 
Container<typename T::element_type*> 
GetRawPtrContainer_helper(Container<T> const &container, ...) { 

    Container<typename T::element_type*> out; 
    for(auto &&e : container) insert(out, e.get(), 0); 

    return out; 
} 

template<typename T, template<typename...> class Container> 
Container<typename T::element_type*> 
GetRawPtrContainer(Container<T> const &container) { 

    return GetRawPtrContainer_helper(container, 0); 
} 

Live Demo