我为集合编写了一个Join
函数,该函数使您可以为任何支持<<
运算符的类之类的字符串创建一个联接字符串。我想对其进行模板化,以便如果您的集合不是一堆字符串,则可以传递一个转换函数,该函数将const引用返回到您想要的“字符串化”字段。
我一直无法弄清楚如何使它成为一个单一的功能模板,但仍然可以与本机数组的集合一起使用。
我希望FunctStringer
默认为一个身份函数,在标准集合的情况下,该函数采用Collection::value_type
,但这也适用于本机数组。
想法?这是模板代码:
// Collection::value_type must be able to be streamed into "output"
template<typename Collection, typename Delimiter, typename Output>
void Join(const Collection &collection, const Delimiter &delimiter, Output &output)
{
if (!std::empty(collection))
{
auto iter = std::begin(collection);
// output the first item
output << *iter;
iter++;
for ( ;iter != std::end(collection); iter++)
{
output << delimiter;
output << *iter;
}
}
}
// Collection::value_type must be able to be streamed into "output"
template<typename Collection, typename Delimiter, typename Output, typename FunctStringer>
void Join(const Collection &collection, const Delimiter &delimiter, Output &output, FunctStringer s)
{
if (!std::empty(collection))
{
auto iter = std::begin(collection);
// output the first item
output << s(*iter);
iter++;
for (; iter != std::end(collection); iter++)
{
output << delimiter;
output << s(*iter);
}
}
}
答案 0 :(得分:1)
如果我理解了这个问题,为什么不喜欢
struct NoOpStringer {
template<class ARG> const ARG& operator()(const ARG& arg) {
return arg;
}
}
然后
template<typename Collection, typename Delimiter, typename Output, typename FunctStringer = NoOpStringer>
void Join(const Collection &collection, const Delimiter &delimiter, Output &output, FunctStringer s = FunctStringer{})
答案 1 :(得分:0)
另一种基于static const
lambda函数的身份函数解决方案。
不幸的是,它需要C ++ 14(使用通用lambda),但是,正如您所看到的,我还修改了该函数以使用range-for循环,因此不再需要迭代器,并且也适用于C样式数组。
#include <vector>
#include <iostream>
static const auto l = [](auto item){ return item; };
template <typename C, typename D, typename O, typename F = decltype(l)>
void Join (C const & c, D const & d, O & o, F f = l)
{
bool first { true };
for ( auto const & item : c )
{
if ( first )
first = false;
else
o << d;
o << f(item);
}
}
int main()
{
std::vector<int> v1 { 2, 3, 5, 7, 11, 13, 17 };
int v2[] { 1, 2, 3, 4, 5 };
Join(v1, ',', std::cout);
std::cout << std::endl;
Join(v2, ',', std::cout, [](auto i){ return i+10; });
std::cout << std::endl;
}