可移植地支持宽松的循环范围
Portably supporting relaxed range-for-loop
C++17 将(可能)relax the definition of the range for loop,允许 end()
到 return 不同的类型(例如哨兵):
struct MyRange {
struct Sentinel {};
int* begin();
Sentinel end();
};
bool operator!=(int*, MyRange::Sentinel);
目前唯一支持此功能的编译器是 gcc 6.1 和 clang 4.0+ (example) (example of error message)。如果我正在编写一个范围类型,其中哨兵对于结束类型会更有效,我如何检测编译器是否支持松弛范围?我在 P0184R0(上面链接)中看不到对此的任何讨论;会提供功能测试宏吗?
更多问题:
- 如果有检测编译器支持的方法,更改我的
end()
成员函数的 return 类型是否安全(对于库)?我需要吗?使我的哨兵隐式转换为我的迭代器类型?
- 相反,对于 C++17 之前的编译器,是否值得以不同的名称(例如
sentinel()
)公开我的哨兵? C++17 之前的算法可以有效地使用 [begin(), sentinel())
还是不值得额外的代码?
哨兵高效的原因很少与哨兵的内部状态有关。
因此,一种方法是为您的 Sentinel
提供足够的内部状态来生成其自身的迭代器版本。
即使在具有统一结束-开始 for(:)
循环和坚持相同 start/finish 迭代器类型的算法的 C++14 中,手写算法或循环也可以使用您的哨兵并提高效率。
如果您想要最大的覆盖范围,像 Boost.Config 这样的库通常是您最好的选择,但截至目前(我可以找到),C++17 功能检测集尚未发布。
据我所知,SFINAE 无法检测接受不同 begin/end 迭代器类型的 for(:)
循环的存在。 (我可以想象一些东西 constexpr
除了一些 hack,但那超出了我的能力。)
检测是否 <algorithms>
接受哨兵结束迭代器可能可以用 SFINAE 完成。但我不确定 C++17 是否已标记 <algorithms>
或什至打算标记; ranges-v3 应该处理那个返工。
Per P0096R3可以检查__cpp_range_based_for
是否大于等于201603,当然Visual Studio不支持any 的功能测试宏,因此您必须单独检查其版本控制。他们在 VS2015 Update 3 中提供了对它的支持,但与大多数其他 C++17 支持一起,您必须使用 /std:c++latest
开关。
C++17 将(可能)relax the definition of the range for loop,允许 end()
到 return 不同的类型(例如哨兵):
struct MyRange {
struct Sentinel {};
int* begin();
Sentinel end();
};
bool operator!=(int*, MyRange::Sentinel);
目前唯一支持此功能的编译器是 gcc 6.1 和 clang 4.0+ (example) (example of error message)。如果我正在编写一个范围类型,其中哨兵对于结束类型会更有效,我如何检测编译器是否支持松弛范围?我在 P0184R0(上面链接)中看不到对此的任何讨论;会提供功能测试宏吗?
更多问题:
- 如果有检测编译器支持的方法,更改我的
end()
成员函数的 return 类型是否安全(对于库)?我需要吗?使我的哨兵隐式转换为我的迭代器类型? - 相反,对于 C++17 之前的编译器,是否值得以不同的名称(例如
sentinel()
)公开我的哨兵? C++17 之前的算法可以有效地使用[begin(), sentinel())
还是不值得额外的代码?
哨兵高效的原因很少与哨兵的内部状态有关。
因此,一种方法是为您的 Sentinel
提供足够的内部状态来生成其自身的迭代器版本。
即使在具有统一结束-开始 for(:)
循环和坚持相同 start/finish 迭代器类型的算法的 C++14 中,手写算法或循环也可以使用您的哨兵并提高效率。
如果您想要最大的覆盖范围,像 Boost.Config 这样的库通常是您最好的选择,但截至目前(我可以找到),C++17 功能检测集尚未发布。
据我所知,SFINAE 无法检测接受不同 begin/end 迭代器类型的 for(:)
循环的存在。 (我可以想象一些东西 constexpr
除了一些 hack,但那超出了我的能力。)
检测是否 <algorithms>
接受哨兵结束迭代器可能可以用 SFINAE 完成。但我不确定 C++17 是否已标记 <algorithms>
或什至打算标记; ranges-v3 应该处理那个返工。
Per P0096R3可以检查__cpp_range_based_for
是否大于等于201603,当然Visual Studio不支持any 的功能测试宏,因此您必须单独检查其版本控制。他们在 VS2015 Update 3 中提供了对它的支持,但与大多数其他 C++17 支持一起,您必须使用 /std:c++latest
开关。