ecatmur ecatmur - 1 year ago 88
C++ Question

Portably supporting relaxed range-for-loop

C++17 will (probably) relax the definition of the range for loop, allowing

to return a distinct type (e.g. a sentinel):

struct MyRange {
struct Sentinel {};
int* begin();
Sentinel end();
bool operator!=(int*, MyRange::Sentinel);

Currently the only compilers that support this are gcc 6.1 and clang 4.0+ (example) (example of error message). If I'm writing a range type where a sentinel would be more efficient for the end type, how can I detect whether the compiler supports relaxed range for? I can't see any discussion of this in P0184R0 (linked above); will a feature test macro be provided?

Further questions:

  • If there is a way to detect compiler support, is it safe (for the library) to change the return type of my
    member function? Do I need e.g. to make my sentinel implicitly convertible to my iterator type?

  • Conversely, for pre-C++17 compilers is it worth exposing my sentinel under a different name (e.g.
    )? Can pre-C++17 algorithms efficiently use
    [begin(), sentinel())
    or is it not worth the additional code?

Answer Source

Per P0096R3, you can check whether __cpp_range_based_fo‌​r is greater than or equal to 201603. Of course, Visual Studio does not support any of the feature test macros, so you'll have to check its versioning separately. They shipped support for it in VS2015 Update 3, but along with most other C++17 support, you have to use the /std:c++latest switch.