LoginSignup
0
1

More than 3 years have passed since last update.

Visual Studio Community 2019 PreviewでC++20 Rangesの主要部分がサポートされた

Last updated at Posted at 2020-09-18

まだプレビュー版なので開発には使えませんが、Visual Studioのプレビュー版(Microsoft Visual Studio Community 2019 Preview Version 16.8.0 Preview 3.0)でC++20のRanges主要機能がサポートされました。

コンセプトと合わせてとてもおもしろい機能だったので、興奮が冷めないうちにRangesとRange adaptorsについて学んだことを記録します。経験に基づく自己流の解釈なので間違っていたら教えてください。

コードの実行時はプロジェクトのプロパティで「C++言語標準」を/std:c++latestに設定します。

Visual Studio 2019 version 16.8 Preview 3 - Visual Studio 2019 Preview Release Notes

Rangesとコンセプト

Rangesは次のrangeのような「コンセプト」を満たす型やそれらに与えられる機能の総称?です。rangeコンセプトの他にもcommon_rangeviewable_rangeが存在します。

template<class T>
concept range = requires(T& t) {
  ranges::begin(t);
  ranges::end(t);
};

参考:https://en.cppreference.com/w/cpp/ranges/range。見やすさのために一部改変。

コンセプトはC++20から導入されたので聞き慣れない単語ですが、これまでメタ関数で複雑に記述していた型の制限をより分かりやすく記述するための方法です。例えば上記のrangestd::ranges::range)はranges::begin(t)ranges::end(t)が適用できるあらゆる型です。

rangeにはSTLコンテナではstd::vectorstd::list等が該当しており、beginendを実装する自作のクラスや構造体も該当します。例えばstd::views::transformrangeから派生したコンセプトviewable_rangeに従う型に適用できるので以下のコードが書けます。

#include <iostream>
#include <ranges>
#include <vector>

class test {
public:
    test() : v{ 0, 1, 2, 3 } {}
    auto begin() { return v.begin(); }
    auto end() { return v.end(); }
private:
    std::vector<int> v;
};

int main()
{
    test t;
    auto mul2 = [](int x) { return x * 2; };
    for (auto x : t | std::views::transform(mul2))
        std::cout << x << std::endl;
    // 0, 2, 4, 6
    return 0;
}

Range adaptors

上のサンプルコードに| std::views::transform(...)という記述が登場しています。このときの呼び出しを順番に説明すると以下の通りです。

  1. std::views::transformstd::views名前空間で定義された_Transform_fn型の変数。
  2. _Transform_fn型は_Copy_constructible_objectコンセプトを満たす型_Fnに対するoperator(_Fn _Fun)を定義しており、transform(...)はこれを呼び出す。
  3. 上記のoperator(_Fn _Fun)_Transform_fn型でprivate定義された_Partial<_Fn>型のオブジェクトを返す。
  4. _Partial<_Fn>型は_Pipe::_Base<_Partial<_Fn>>型から派生しており、この_Pipe::_Base<_Partial<_Fn>>型が定義する右辺用の|演算子が呼び出される(| std::views::transform(...)|)。
  5. _Partial<_Fn>型はtransform_viewを返す()演算子を定義しており、上記の|演算子がこれを呼び出す。

<ranges>の中を行ったり来たりしますが、コンセプトという新機能を使った見事な仕組みです。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1