在集合上运行的功能模板,该模板具有默认的“转换”功能,该功能不执行任何操作

时间:2019-03-26 17:36:32

标签: c++ templates

我为集合编写了一个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);
            }
        }
    }

2 个答案:

答案 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;
 }