我想创建一个模板函数,该函数生成一个具有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();
}
}
};
正如您可以清楚地看到的,有一个束的重复,特别是在参考专业化之间。我不是很快就用最好的方法来做到这一点,我希望看到更好的方法来删除一些或所有代码重复
答案 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; }
};