2017-04-10 30 views
1

テンプレートテンプレートパラメータを持つこの単純な関数があります。 (それがC++ 03のプロジェクトだが、私はまた、C++ 11のための答えに興味がある)、STLコンテナを取る通常のPTRにスマートPTRを変換するためのものです:テンプレートテンプレートクラス、存在する場合は関数を呼び出す

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であれば、これはstd::liststd::dequeの罰金ですが、その後、O(1)挿入のパフォーマンスの問題が、ありますことに気づいたかもしれません。だから、(コンパイル時に決定)が可能かどうループ前コールこれをは私がやりたいものです:

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

機能しますif reserveはif可能:

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) 
{ 
} 

ちょうどあなたのループの前にご予約関数を呼び出すと、あなたはそれがしたいようにそれが動作するはずです。

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 :: W.F @ 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

ためenable_if。それは本当です、私は編集:) – amchacon

0

はここでコンテナは不可知論だと埋蔵量が入力コンテナは.reserveメンバ関数を持っている場合には、バッファC++ 11実装のオーバーロードを使用することができます。

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

関連する問題