2016-08-15 19 views
1

C++ 17將(可能)relax the definition of the range for loop,允許end()返回一個不同的類型(例如定點):便攜地支撐鬆弛範圍-for循環

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

目前支持此唯一的編譯器的gcc 6.1和鐺4.0+(example)(example of error message)。如果我正在編寫一個範圍類型,其中標記對於最終類型更有效,那麼如何檢測編譯器是否支持輕鬆範圍?我在P0184R0中看不到有關這方面的任何討論(上面鏈接);將提供一個功能測試宏?

的其他問題:

  • 如果沒有檢測到編譯器支持的一種方式,它是安全(對於庫)改變我end()成員函數的返回類型?我是否需要使我的哨兵隱式轉換爲我的迭代器類型?相反,對於C++ 17之前的編譯器,值得以不同的名稱公佈我的哨兵(例如sentinel())?預C++ 17算法能否有效地使用[begin(), sentinel())還是不值得額外的代碼?
+0

根據[P0096R3](http://wg21.link/p0096r3),你可以檢查'__cpp_range_based_for'是否大於或等於201603. – cpplearner

+0

@carrarner啊,當然。請做出答案,我會接受它。 – ecatmur

回答

3

P0096R3,你可以檢查__cpp_range_based_fo‌​r是否大於或等於201603.當然,Visual Studio中不支持的功能測試宏任何,所以你必須單獨檢查其版本。他們在VS2015 Update 3中提供了對它的支持,但隨着大多數其他C++ 17支持,您必須使用/std:c++latest開關。

2

哨兵高效的原因很少與哨兵的內部狀態有關。

所以一種方法是給你的Sentinel足夠的內部狀態來生成自己的迭代器版本。即使在C++ 14中使用統一的末端開始for(:)循環和算法也堅持相同的開始/結束迭代器類型,手寫算法或循環可以使用您的哨兵和增益效率。

Boost.Config這樣的圖書館通常是你最好的選擇,如果你想要最大的覆蓋範圍,但是C++ 17功能檢測集還沒有在這個日期發佈(我可以找到)。

據我所知,沒有辦法通過SFINAE檢測接受不同開始/結束迭代器類型的for(:)循環的存在。 (我可以想象constexpr不包括某些黑客行爲,但這超出了我的技能範圍。)

檢測<algorithms>是否接受哨兵結束迭代器可能可以用SFINAE完成。但即使C++ 17已經定位爲<algorithms>甚至有意,我也不確定;範圍-V3應該處理返工。