2017-04-10 173 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