如何默认构造迭代器的value_type作为函数中的默认参数?

时间:2017-02-17 19:05:03

标签: c++ templates iterator c++14 default-constructor

这是可憎的:

T

所以我希望默认情况下std::iterator_traits<BidirIt>::value_typeinit,默认情况下构造一个该类型的对象,为其命名T

在解决了在一行中拟合某些变量类型的问题之后,我发现编译器无法推导出std::vector<int> v(window_length + window_count - 1); std::iota(v.begin(), v.end(), 0); std::vector<int> output(window_count); std::vector<int> correct_result{3, 6, 9, 12}; sliding_window(v.begin(), v.end(), output.begin(), window_length/*, 0, std::plus<>(), std::minus<>()*/); ,这就是它的确切说法:

  

错误:没有匹配函数来调用&#39; sliding_window&#39;       sliding_window(v.begin(),v.end(),output.begin(),window_length / ,0,std :: plus&lt;&gt;(),std :: minus&lt;&gt;() /);

     

注意:候选模板被忽略:无法推断模板参数&#39; T&#39;   void sliding_window(BidirIt first,BidirIt last,OutputIt d_first,

我的编译器是clang ++ - 3.9。

致电网站代码:

std::iterator_traits<BidirIt>::value_type

当注释部分被取消注释时,代码可以正常工作。

根据我对模板的了解,它应该能够推断出那种类型,因为它实际上是一个默认的构造函数调用,它应该产生{{1}}。当函数在类型上模板化时,我是否对默认参数的类型有何误解?

问题:如何解决?给它添加一些解释也会很棒。

2 个答案:

答案 0 :(得分:4)

无法从默认的模板化参数中推断出模板类型:C++14 lambda's default argument type deduction depending on preceding arguments。至于如何修复它,您需要默认类型:

template <typename BidirIt, typename OutputIt,
    typename T = typename std::iterator_traits<BiDirIt>::value_type,
    typename BinaryDoOp = std::plus<>,
    typename BinaryUndoOp = std::minus<>>
void sliding_window(BidirIt first, BidirIt last, OutputIt d_first,
                typename std::iterator_traits<BidirIt>::difference_type length,
                T init = T{},
                BinaryDoOp op = BinaryDoOp{},
                BinaryUndoOp undo = BinaryUndoOp{})

另一种方法也是重载函数,其中模板参数/参数较少的函数调用具有更多函数的函数并处理调用站点的默认值。这是std::accumulate使用的方法:http://en.cppreference.com/w/cpp/algorithm/accumulate。然后你会有多个函数,所以那里有一些重复,但每一个都有更多的可读性。

答案 1 :(得分:1)

应该是:

template <typename BidirIt,
          typename OutputIt,
          typename T = typename std::iterator_traits<BidirIt>::value_type,
          typename BinaryDoOp = std::plus<>,
          typename BinaryUndoOp = std::minus<>>
void sliding_window(BidirIt first,
                    BidirIt last,
                    OutputIt d_first,
                    typename std::iterator_traits<BidirIt>::difference_type length,
                    T init = {},
                    BinaryDoOp op = {},
                    BinaryUndoOp undo = {})

模板类型不是从默认值推导出来的。 所以你必须手动设置默认类型。