2

我有一个算法,它采用两个范围并返回一个迭代的范围,动态计算,第一个范围中元素的特殊子集,基于第二个范围的内容。特殊子集本身又可以在另一个集合上通过该算法运行。一切正常,但我正在努力尝试使用可变参数模板改进 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";
}

我想人们可以求助于宏,但似乎我正在拍摄的东西应该可以通过可变参数模板实现。我只是不够敏锐,无法弄清楚,我对错误感到困惑。有没有办法只用一个模板函数来做到这一点?还是你必须用容器语义构建一个类似元组的东西?如果是这样,怎么做?

4

1 回答 1

3

除此之外,

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

也定义这个,

//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...);
}

注意尾随返回类型。

它是如何工作的?

如果有超过 2 个参数,将调用第二个重载,否则将调用第一个重载。

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

于 2013-04-07T14:29:12.390 回答