首页 > 解决方案 > 为不同的容器定义一个函数

问题描述

我想定义一个接受不同类型容器的函数:拥有数据的容器(如std::vector)和不拥有数据的容器(如boost::iterator_range)。

我写了以下内容:

#include <vector>
#include <boost/range/iterator_range.hpp>

template<typename C>
void fill(C& c, typename C::value_type v){
    for (auto& j : c)
        j = v;
}


template<typename C>  // How to avoid this implementation?
void fill(const C& c, typename C::value_type v){
    for (auto& j : c)
        j = v;
}

int main(){
    std::vector<int> v(10);
    auto rng = boost::make_iterator_range(v.begin(), v.end());


    fill(v, 1);  // Case 1 -- Calling on std::vector
    fill(rng, 2); // Case 2 -- Calling on boost::iterator_range

    // Case 3 -- Calling with an r-value, requires the overload
    fill(boost::make_iterator_range(v.begin(), v.end()), 3);

    // Case 4 -- Should not be allowed
    // fill(std::vector<int>(10), 4);
}

我的第一个实现fill效果很好,因为它接受了两种迭代器。

但是,由于boost::iterator_range不拥有数据,它可以是const(当数据是非常量时),所以我想允许右值作为参数。这意味着我需要第二个实现。

这是唯一的方法吗?有没有办法避免第二次实施?

标签: c++boostiterator

解决方案


您可以使用完美转发:

template <typename C>
void fill(C&& c, typename std::decay_t<C>::value_type v) {
    for (auto& j : c)
        j = v;
}

这实际上并不是“完美转发”,因为您不希望利用移动语义,如果您愿意,您应该编写std::forward<C>(c)而不是c¹

住在科利鲁

#include <boost/range/iterator_range.hpp>
#include <vector>

template <typename C>
void fill(C&& c, typename std::decay_t<C>::value_type v) {
    for (auto& j : c)
        j = v;
}

int main() {
    std::vector<int> v(10);
    auto rng = boost::make_iterator_range(v.begin(), v.end());

    fill(v, 1);   // Case 1 -- Calling on std::vector
    fill(rng, 2); // Case 2 -- Calling on boost::iterator_range

    // Case 3 -- Calling with an l-value, requires the overload
    fill(boost::make_iterator_range(v.begin(), v.end()), 3);
}

¹ 请注意,如果您这样做,您必须小心不要在移动后使用。


推荐阅读