使用boost :: any_range有什么好处?

时间:2013-03-15 21:22:30

标签: c++ boost stl type-erasure boost-range

使用boost::any_range有什么好处? 这是一个例子:

typedef boost::any_range<
    int
  , boost::forward_traversal_tag
  , int
  , std::ptrdiff_t
> integer_range;

void display_integers(const integer_range& rng)
{
    boost::copy(rng,
                std::ostream_iterator<int>(std::cout, ","));

    std::cout << std::endl;
}

int main(){
    std::vector<int> input{ ... };
    std::list<int> input2{ ... };
    display_integers(input);
    display_integers(input2);
}

但是使用模板参数可以实现更高效的相同功能,该参数满足ForwardRange概念:

template <class ForwardRange>
void display_integers(const ForwardRange& rng)
{
    boost::copy(rng,
                std::ostream_iterator<int>(std::cout, ","));

    std::cout << std::endl;
}

所以我正在寻找值得使用any_range的场景。也许我错过了什么。

2 个答案:

答案 0 :(得分:17)

这种技术称为Type Erasure。有一篇完整的文章描述了any_iteratorOn the Tension Between Object-Oriented and Generic Programming in C++示例的优缺点。

可以隐藏(在单独的文件/库中)

的实现/定义
void display_integers(const integer_range& rng)

但是在

的情况下
template <class ForwardRange>
void display_integers(const ForwardRange& rng)

您必须向用户提供源代码(或至少在某处制作explicit instantiations)。

此外,在第一种情况下,display_integers将只编译一次,但在第二种情况下,它将针对传递范围的每种类型进行编译。

另外,你可能有某个地方

integer_range rng;

并且在rng的生命周期内,您可以指定different types to it的范围:

vector<int> v;
list<int> l;
integer_range rng;
rng = v;
rng = l;

类型擦除的最大缺点是其运行时成本;所有操作都是虚拟的,无法内联(轻松)。


P.S。另一个着名的类型擦除示例是std::function

答案 1 :(得分:10)

boost::any_range可用于从函数返回范围。想象一下以下示例:

auto make_range(std::vector<int> v) -> decltype(???)
{   
    return v | filter([](int x){ return x % 2 == 0;})
        | transform([](int x){ return x * 2;});
}

*:gcc不编译上面的内容而不将其包装在std::function中,hower clang 3.2的工作方式是直接传递lambda

很难知道从这个函数返回什么。此外,lambda and decltype不能一起工作,因此我们无法在仅传递lambda时使用decltype来推断类型。一种解决方案是使用boost::any_range,例如示例中的std::function(另一种解决方法是使用评论中Evgeny Panasyuk指出的integer_range make_range(std::vector<int> v) { return v | filter([](int x){ return x % 2 == 0;}) | transform([](int x){ return x * 2;}); } ):

std::function

使用{{1}}的工作示例with gcc

工作示例with clang直接传递lambdas。