如何使基于范围的循环在GCC 4.9.3中兼容旧版ROOT框架?
GCC 4.9.3 + ROOT 6.04.16 下RooFit容器范围循环兼容方案
问题根源
- GCC 4.9.3本身支持C++11范围for循环,但要求通过**参数依赖查找(ADL)**能找到对应容器的
begin()/end()函数——要么是容器的成员函数,要么是容器所在命名空间下的全局重载。 - ROOT 6.04.16的RooFit容器(如
RooArgSet、RooArgList)还未内置范围循环支持,既没有成员begin()/end(),也没在对应命名空间提供全局重载。 - 你之前写的迭代器助手重载大概率没放在正确的命名空间,导致ADL无法识别,所以编译报错。
可行解决方法:自定义begin()/end()重载
1. 把重载放在正确的命名空间
将begin()/end()重载放到RooFit命名空间下(和RooArgSet/RooArgList同命名空间),这样ADL会自动匹配到:
#include "RooArgSet.h" #include "RooArgList.h" namespace RooFit { // RooArgSet 非const版本 RooAbsArg** begin(RooArgSet& set) { return set.array(); } RooAbsArg** end(RooArgSet& set) { return set.array() + set.size(); } // RooArgSet const版本 const RooAbsArg** begin(const RooArgSet& set) { return set.array(); } const RooAbsArg** end(const RooArgSet& set) { return set.array() + set.size(); } // RooArgList 非const版本 RooAbsArg** begin(RooArgList& list) { return list.array(); } RooAbsArg** end(RooArgList& list) { return list.array() + list.size(); } // RooArgList const版本 const RooAbsArg** begin(const RooArgList& list) { return list.array(); } const RooAbsArg** end(const RooArgList& list) { return list.array() + list.size(); } }
2. 调整头文件包含顺序
在使用范围循环的业务代码前,先包含上述重载的头文件,再引入ROOT的RooFit相关头文件,避免提前触发编译错误。
3. 确认编译选项
GCC 4.9.3需要显式开启C++11支持,编译时必须加上-std=c++11参数(默认可能未启用,导致范围循环特性被禁用)。
验证注意事项
- 重载函数的返回类型必须和容器
array()方法的返回值匹配(RooAbsArg**或const RooAbsArg**),end()要指向最后一个元素的下一个位置,确保循环边界正确。 - 必须同时提供const版本的重载,否则const容器对象使用范围循环时会编译失败。
内容的提问来源于stack exchange,提问作者carsten
相关产品推荐
相关产品推荐

