表达式模板和基于C++11中的范围
Expression templates and ranged based for in C++11
我的理解是,表达式模板在C++11中会破坏基于ranged的for,因为for (auto x : expr)
中有一个隐式auto&& __range = expr
,这将导致悬空引用。
有没有一种方法可以创建表达式模板类,使它们在基于范围的for中正确运行,或者至少引发编译错误?
基本上,我想防止表达式模板正确编译但在运行时由于悬挂引用而失败的可能性。我不介意在基于范围的for中使用表达式模板之前必须将其包装在某种东西中,只要用户忘记包装表达式模板时不会出现静默运行时错误。
通常对此无能为力。如果给定一个表达式作为范围,则它必须解析为for
语句初始化后有效的值。并且在编译时无法检测到任何特定类型是由auto
推导出来的。
最好使您的表达式系统更加基于移动,这样它就不必包含引用。与尝试存储对潜在死东西的引用相比,auto
将产生更安全的结果。如果不可移动类型的复制让你感到困扰,那就接受它吧。
我能想到几个选项,每个选项都有自己的丑陋之处。
一个明显的选择是使用指针(可能是unique_ptr
)而不是引用。当然,为了实现这一点,它要么需要来自堆的分配,要么需要自定义分配器。我认为,对于一个好的分配器,这种方法有一些优点。再说一遍,操作员超载只会变得很糟糕。
另一种方法是按值存储子表达式,而不是按常量引用存储。这种方法的效率非常依赖于编译器,但由于你基本上要处理一堆临时文件,我想现代编译器可以优化掉副本(或者至少是很多副本)。
最后一种方法允许您对代码保持相同的结构,但强制用户计算表达式。它要求您只有一个可迭代类型,即表达式的底层类型(比如std::vector<int>
)。任何表达式类都不应该为它们定义begin
和end
方法或函数,而应该只转换为基础类型。这样,像for(auto x : expr)
这样的代码在编译时会失败(因为expr
是不可迭代的),但编写for(auto x : static_cast<vector<int>>(expr))
是有效的,因为表达式已经求值了。
如果希望使用基于范围的for循环来实现表达式模板操作,那么可以在表达式模板类中提供私有或受保护的begin
和end
方法。只需确保每个模板类都可以访问其他模板类的begin
和end
方法。在这种情况下应该是可以的,因为表达式模板是函数的参数,所以在该函数中编写循环时不必担心悬挂引用。
- C ++枚举范围无法使用-std=c ++ 98进行编译,但使用-std=c ++ 11可以
- C++11 基于范围的 for 循环,用于 std::list
- C++11:没有复制构造函数的自定义基于范围的循环
- 如何在C++11中区分填充构造函数和范围构造函数
- 自动和范围内 for 循环 C++11 不起作用
- 带钥匙的C 11地图定义了一个值范围
- 为什么即使在启用 C++11 并且我包含字符串之后,'stod'仍然没有在此范围内声明?
- C++11 迭代器和返回的 std::unique_ptr 的范围
- C++11:用容器参数定义函数(类似于基于范围的)
- GCC 4.4 不实现 C++11 范围循环.它还支持哪些其他范围循环语法
- 嵌套c++11范围循环,用于查找组合
- 使用基于C++11范围的循环验证数组值?[无矢量]
- 基于C++11范围的自动循环(按值、引用和指针)
- 使用对指针的引用作为循环C++11范围内的序列
- 从矢量中删除项目,而在 C++11 范围内'for'循环?
- 在基于 C++11 范围的'for'循环中获取对 STL 容器元素的引用
- C++11范围内的随机数和显式相似性
- 多维数组上循环的C++11范围
- 关于循环和迭代器的c++11范围
- C++11 范围超过 "tuple"