2012-04-14 13 views
1

name()メソッドを持つ配列の文字列表現を生成するテンプレート関数を作成したいとします。物事値によって、または参照(生またはスマート)によって保持される可能性がありますオブジェクトのベクトルのテンプレート文字列表現

 template< typename T> 
     struct GetStringRepresentation; 

     template< typename T> 
     struct GetStringRepresentation< std::vector< std::unique_ptr<T> > > 
     { 
      inline void()(const std::vector< std::unique_ptr<T> >& seq, std::string& out) 
      { 
       size_t size = seq.size(); 
       for (int i=0; i< size; i++) 
       { 
        if (i > 0) 
         out += ", "; 
        out += seq[i]->name(); 
       } 
      } 
     }; 

     template< typename T> 
     struct GetStringRepresentation< std::vector< std::shared_ptr<T> > > 
     { 
      inline void()(const std::vector< std::shared_ptr<T> >& seq, std::string& out) 
      { 
       size_t size = seq.size(); 
       for (int i=0; i< size; i++) 
       { 
        if (i > 0) 
         out += ", "; 
        out += seq[i]->name(); 
       } 
      } 
     }; 

     template< typename T> 
     struct GetStringRepresentation< std::vector< T* > > 
     { 
      inline void()(const std::vector< T* >& seq, std::string& out) 
      { 
       size_t size = seq.size(); 
       for (int i=0; i< size; i++) 
       { 
        if (i > 0) 
         out += ", "; 
        out += seq[i]->name(); 
       } 
      } 
     }; 

     template< typename T> 
     struct GetStringRepresentation< std::vector<T> > 
     { 
      inline void()(const std::vector<T>& seq, std::string& out) 
      { 
       size_t size = seq.size(); 
       for (int i=0; i< size; i++) 
       { 
        if (i > 0) 
         out += ", "; 
        out += seq[i].name(); 
       } 
      } 
     }; 

あなたがはっきりと見ることができるように、重複のは特別に参照専門分野の間で、そこにあります。私はこれを行う最善の方法でスピードアップするつもりはありません、私はコードの重複のいくつか、またはすべてを削除するより良い方法を見たいと思います。

答えて

4

ここでは始めるためのヒントです:のみ:

template <typename T> void print(T const & x) 
{ 
    std::cout << printer<T>::print(x) << std::endl; 
} 

template <typename T> struct printer 
{ 
    static std::string print(T const & x) { return x.name(); } 
}; 
template <typename U> struct printer<U*> 
{ 
    static std::string print(U * p) { return p->name(); } 
}; 

この方法では、ループを1回書く必要があり、プリンタは詳細を処理します。あなたも、抽象、この更することができますし、今度はあなたがすべてのスマートポインタのための専門is_pointer_like特性(->をサポートしているすべてのもの)の一種、作る:pretty printerを参照して、同様のアイデアについて

printer<T, is_pointer_like<T>::value>::print(x); // etc. 

template <typename T, bool> struct printer { /* as before */ } 

template <typename T> struct printer<T, true> 
{ 
    static std::string print(T const & p) { return p->name(); } 
}; 

// Traits: 
template <typename T> struct is_pointer_like : std::false_type { }; 
template <typename U> struct is_pointer_like<U*> : std::true_type { }; 
template <typename U> struct is_pointer_like<std::shared_ptr<U>> : std::true_type { }; 

を。

1

私はこれを記述します。

struct GetStringRepresentation 
{ 
    template<typename T> 
    std::string operator()(std::vector<T> const & seq) 
    { 
     std::string out; 
     size_t size = seq.size(); 
     for (size_t i=0; i< size; i++) 
     { 
      if (i > 0) 
       out += ", "; 
      out += get(seq[i]); //call get() to get the string 
     } 
     return out; 
    } 

private: 

    template<typename T> 
    std::string const & get(T const & t) { return t.name; } 

    template<typename T> 
    std::string const & get(T const * t) { return t->name; } 

    template<typename T> 
    std::string const & get(std::unique_ptr<T> const & t) { return t->name; } 

    template<typename T> 
    std::string const & get(std::shared_ptr<T> const & t) { return t->name; } 
}; 
関連する問題