Расширение оператора switch

Евгений Красников
Евгений Красников

Предлагаю расширение оператора switch, чтобы можно было перечислять несколько значений через запятую, использовать нецелочисленные значения, переменные, сравнения со значениями.

 

Код:

switch (letter) {
  case 'a': case 'e': case 'i': case 'o': case 'u':
    ++vowels;

}

было бы удобнее использовать так:

switch (letter) {
  case 'a', 'e', 'i', 'o', 'u':
    ++vowels;

}

 

Другой пример. Почему бы не сделать возможность замены:

if (str == "hello") { std::cout << "Hi!"; }
else if (str == "bye") { std::cout << "See ya!"; }
else { std::cout << "Let's talk!"; 
}

на:

switch (str) {
  case "hello":
    std::cout << "Hi!";
    break;
  case "world":

    std::cout << "See ya!";
    break;
  default:
    std::cout << "Let's talk!";
}

 

Ну и, наконец:

switch (value) {
  case < 0:
    // less than 0
    break;
  case >= 10:

    // greater or equal to 0
    break;
  case x:
    // equal to x
    break;
  case_all > y, < z:
    // greater than y and less than z
    break;
  default:
    // else branch
}

В последнем случае допустимы операторы сравнения ==, !=, >, <, >=, <=, следующие сразу за case или запятой. Значения проверяются последовательно, т.е. если удовлетворяется несколько условий, то прыжок идёт на метку, объявленную выше по коду.

Синтаксис case_all, означающий соблюдение сразу всех условий, вероятно, не лучший, но смысл таков :)

7
рейтинг
2 комментария
al-mission-2016

Всё это, и даже больше, скорее всего будет добавлено в C++23, поскольку улучшение механизмов поиска по образцу (pattern matching) - один из приоритетов C++23. Только синтаксис будет немного другой - switch по ряду причин решили не трогать. Скорее всего введут ключевое слово inspect. В итоге будет свич не только по числам и по строкам, но даже по типам.

al-mission-2016
al-mission-2016

Например (предварительный синтаксис):

    // По числам:
    inspect (x) {
        42:  print("Параметр Хабла Ho: 42 мили/в секунду/на мегапарсек");
        43:  print("Это 43");
        __:  print("не важно");
    }

    // По строкам:
    inspect (s) {
        "foo": print("фу");
        "bar": print("бар");
        __:    print("default");
    }

    // По полиморфным типам, [r], [w, h] ниже - это капчинг членов-данных:
    int get_area(const Shape& shape) const {
        return inspect (shape) {
            <Circle> [r] => 3.14 * r * r,
            <Rectangle> [w, h] => w * h
        }
    }

Также inspect будет визитёром для std::tuple, std::variant, std::any.

    // Поддержка std::variant<Cube, Shape>:
    inspect (var) {
        <Cube>   c: print("Volume = {}", pow(c.edge(), 3));
        <Sphere> s: print("Volume = {}", 4./3 * pi * pow(s.radius(), 3));
    }

В общем, смотрите пропозал Pattern Matching (поиск по паттерну) 

[P1371R2 - C++23 - Pattern Matching (поиск по паттерну). 2020-01-13](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2020/p1371r2.pdf)

al-mission-2016
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).
Все предложения