可移植地支持宽松的循环范围

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(上面链接)中看不到对此的任何讨论;会提供功能测试宏吗?

更多问题:

哨兵高效的原因很少与哨兵的内部状态有关。

因此,一种方法是为您的 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_fo‌​r是否大于等于201603,当然Visual Studio不支持any 的功能测试宏,因此您必须单独检查其版本控制。他们在 VS2015 Update 3 中提供了对它的支持,但与大多数其他 C++17 支持一起,您必须使用 /std:c++latest 开关。