模板字符串表示对象的向量

时间:2012-04-14 16:28:03

标签: c++ templates typetraits

我想创建一个模板函数,该函数生成一个具有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();
                }
            }
        };

正如您可以清楚地看到的,有一个的重复,特别是在参考专业化之间。我不是很快就用最好的方法来做到这一点,我希望看到更好的方法来删除一些或所有代码重复

2 个答案:

答案 0 :(得分: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(); }
};

这样你只需要编写一次循环,打印机就会处理细节。你甚至可以进一步抽象出来并制作一种is_pointer_like特征(支持->的所有特征),这反过来又专门用于所有智能指针:

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

有关类似的想法,请参阅pretty printer

答案 1 :(得分: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; }
};