将任意数量的迭代器对折叠成一个新的迭代器.元编程以获得良好的语法

Fold arbitrary number of pairs of iterators into a new iterator. Metaprogramming for a nice syntax?

本文关键字:迭代器 编程 语法 一个 任意数 折叠      更新时间:2023-10-16

我有一个算法,它接受两个范围并返回一个范围,该范围根据第二个范围的内容动态地迭代计算第一个范围中元素的特殊子集。这个特殊子集本身又可以在另一个集合上通过这个算法运行。一切都很好,但我一直在努力用可变模板改进api。下面main函数的最后一个子句说明了这个目标。

template <class ContainerLeft, class ContainerRight>
class joincalc_const_iter : public std::iterator<std::input_iterator_tag, typename ContainerLeft::difference_type> {
public:
    joiner_const_iter& operator++(); /* does complicated stuff to find the next member of a subset in left. */
    const typename ContainerLeft::value_type& operator*() const;
    const ContainerLeft* left = nullptr;
    const ContainerRight* right = nullptr;
...
};
template <class ContainerLeft, class ContainerRight>
class JoinCalc {
public:
    typedef joincalc_const_iter<ContainerLeft, ContainerRight> const_iterator;
    const_iterator begin() const;
    const_iterator end() const;
...
};
template<class L, class R>
JoinCalc<L, R> join(const L& left, const R& right)
{
    return JoinCalc<L, R>(left, right);
}
int main()
{
    SomeSequence a{...}, b{...};
    SomeSequenceDifferentType c{...}, d{...};
    /* Works great. */
    for (const auto& n : join(a, c))
        std::cout << n << "n";
    for (const auto& n : join(a, b))
        std::cout << n << "n";
    /* Works, but is a pain to write. I'm trying and failing at using variadic
     * templates to automate this. The goal is to write: join(a, b, c, d); */
    for (const auto& n : join(join(join(a, b), c), d))
        std::cout << n << "n";
}

我想一个人可以求助于宏,但似乎我所拍摄的应该是可变模板。我只是不够敏锐,不能算出来,我被错误弄糊涂了。是否有一种方法来做到这一点,只是一个模板函数?还是必须用容器语义构建类似元组的东西?如果有,怎么做?

除此之外,

template<class L, class R>
JoinCalc<L, R> join(const L& left, const R& right)
{
    return JoinCalc<L, R>(left, right);
}

define this also,

//it is an overload, not specialization
template<class L, class R, class ...Rest>
auto join(const L& left, const R& right, Rest const & ... rest) 
                    -> decltype(join(JoinCalc<L, R>(left, right), rest...))
{
    return join(JoinCalc<L, R>(left, right), rest...);
}

注意尾随返回类型

它是如何工作的?

如果有两个以上的实参,将调用第二个重载,否则将调用第一个重载。

顺便说一下,我建议您接受参数作为通用引用,并使用std::forward将参数转发给构造函数和其他重载。