C++ 使用boost::any_范围有什么好处?

C++ 使用boost::any_范围有什么好处?,c++,boost,stl,type-erasure,boost-range,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::os

使用
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);
}
typedef boost::任意_范围<
int
,boost::前向遍历标记
,int
,std::ptrdiff\t
>整数范围;
无效显示整数(常量整数范围(&rng)
{
boost::复制(rng,
std::ostream_迭代器(std::cout,“,”);

std::cout这种技术被称为类型擦除。有一篇完整的文章描述了
任何迭代器的优缺点

可以隐藏(在单独的文件/库中)的实现/定义

void display_integers(const integer_range& rng)
但在这种情况下

template <class ForwardRange>
void display_integers(const ForwardRange& rng)
rng
的生命周期内,您可以分配以下范围:

向量v; 清单l; 整数范围rng; rng=v; rng=l;
类型擦除的最大缺点是其运行时成本;所有操作都是虚拟的,并且不能内联(轻松地)



另外,另一个著名的类型擦除示例是

boost::任何范围
都可以用于从函数返回范围。想象以下示例:

auto make_range(std::vector<int> v) -> decltype(???)
{   
    return v | filter([](int x){ return x % 2 == 0;})
        | transform([](int x){ return x * 2;});
}
使用
std::function
的工作示例


直接传递lambda的工作示例。

除了隐藏实现之外,编译器将生成
display_integers
函数的单个定义,而不是为曾经使用过的每个迭代器类型生成一个版本。这称为代码膨胀。@DavidRodríguez dribeas,我已经说过:“在第一种情况下,display_整数将只编译一次…”。但是请注意,在类型擦除的情况下,当您传递不同类型的值时,将生成不同的“实现”类,这不是“免费的”。是的,我只是想强调,直接的含义是减少模板代码膨胀,而不是为{Ranges}x{Algorithms},类型擦除(any_range)将涉及{Ranges}x{any_range specializations}的一些代码生成(当然这并不严格-取决于实际使用的组合)无论如何,对我来说,我认为主要的优势不在于减少了二进制代码的大小,而在于减少了依赖性,并且能够在独立库中完全隔离所有实现细节,而无需向用户公开代码。这不一定是真的;如果模板的编码方式能够隔离任何与类型无关的代码,则“膨胀”"由模板化代码引起的问题可以大大减少。这在大多数
std::map
的实现中都可以看到,它们在
void*
方面有一个红黑树实现,这在
std::map
的任何实例化之间都是保守的。实际上,模板只是一个更通用的底层数据类型的适配器。I我想这个问题也可以通过另一种方式解决:在细节或隐藏的命名空间中定义一个全局lambda变量,然后使用该lambda变量的decltype。下面是一个完整的工作示例:@GaborMarton:对,请记住可能有。在这种情况下(作为回答)-lambda没有问题,因为您确实使用std::function.decltype(v | boost::adapters::filtered(std::function{}))@evgenypanasuk:谢谢你指出这一点!我把这个例子弄得更复杂了,所以
decltype
无法推断出来。@JesseGood,仍然可以使用decltype-。你可以删除std::function,然后将lambda直接传递给boost::adapters::filtered-
integer_range rng;
vector<int> v;
list<int> l;
integer_range rng;
rng = v;
rng = l;
auto make_range(std::vector<int> v) -> decltype(???)
{   
    return v | filter([](int x){ return x % 2 == 0;})
        | transform([](int x){ return x * 2;});
}
integer_range make_range(std::vector<int> v)
{
     return v | filter([](int x){ return x % 2 == 0;})
        | transform([](int x){ return x * 2;});
}