cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
89 stars 0 forks source link

Добавить в С++ switch constexpr #339

Open apolukhin opened 3 years ago

apolukhin commented 3 years ago

Перенос предложения: голоса +24, -1 Автор идеи: Игорь Шаповал

В С++17 была добавлена конструкция if constexpr. Проверка условия во времени компиляции во многих случаях делает код более четабельным. Было бы не плохо добавить подобную конструкцию - switch constexpr. Например, мы имеем класс для конфига

class config {
private:
    int id, age;
    string name;
public:
    config(int id, int age, const string& name) :
        id(id), age(age), name(name) {}
};

Мы хотим применить structured binding к классу. Мы должны для своего класса переопределить get(), std::tuple_size, std::tuple_element. Метод get() мы можем реализовать вот так

template <std::size_t N>
decltype(auto) get() const {
    if constexpr (N == 0) {
        return id;
    } else if constexpr (N == 1) {
        return age;
    } else if constexpr (N == 2) {
        return (name);
    }
}

С switch constexpr можно было бы написать вот так

template <std::size_t N>
decltype(auto) get() const {
    int result;

    switch constexpr (N) {
    case 0:
        result = id;
        break;
    case 1:
        result = age;
        break;
    case 2:
        result = (name);
        break;
    default:
        result = -1;
    }

    return result;
}
apolukhin commented 3 years ago

Sasha Sitnikov, 7 августа 2018, 17:37

    case 2:
        result = (name);

Как это должно работать? name типа string, а result - int.

Игорь Шаповал, 7 августа 2018, 17:50 Сори, переменная result должна быть типа decltype(auto)

decltype(auto) result;

Sasha Sitnikov, 7 августа 2018, 19:16 Игорь Шаповал, то есть, за одно добавить еще и deferred type deduction? Это само по себе не маленькое изменение

Andrey, 7 августа 2018, 22:53 if отличается от switch тем, что его ветки then, else взаимоисключающие -- компилируется всегда ровно одна из них. switch же не обладает такой стройной структурой -- технически его тело вообще не имеет структуры (разбиения на ветки) -- это просто compound statement в некоторых местах которого расставлены labels. Поэтому неясно, должны ли какие-то части тела constexpr switch исключаться из компиляции, если да -- то по каким правилам, если нет -- то даже Ваш пример с get не скомпилируется -- так как функция будет иметь несколько return statement с аргументами разного типа.

Игорь Шаповал, 8 августа 2018, 9:13 Пример с get() работает. Использовал structured bindings в проекте для класса.

Andrey, 8 августа 2018, 11:28 Игорь Шаповал, Вы имеете в виду если использовать constexpr if? Да работает, потому что неподходящие ветки просто отбрасываются компилятором. Я писал про то, что это же придется как-то делать с constexpr switch, но его тело не делится четке на ветки.

Игорь Шаповал, 8 августа 2018, 12:51 Но согласитесь было бы классно иметь такую фичу в языке.

dreverser, 9 августа 2018, 8:01 что уж там, давате сделаем весь С++ constexpr-ом

Саша Зайцев, 9 августа 2018, 15:15 dreverser, вот Вы смеётесь, а всё ведь к этому и идёт...

yndx-antoshkka, 9 августа 2018, 16:24

что уж там, давате сделаем весь С++ constexpr-ом

Мы работаем над этим :)

dreverser, 9 августа 2018, 22:49 так я и говорю, бросайте по 1/100 языка втягивать в constexpr

дайте установку дядкам сразу, к такому то стандарту весь С++ будет constexpr

yndx-antoshkka, 10 августа 2018, 14:04 Слона надо есть по кускам, иначе он не помещается в рот... Сделать одним махом всё constexpr не получится - подобное предложение будет перевариваться в комитете десятилетия.

Игорь Шаповал, 10 августа 2018, 16:12 yndx-antoshkka Скажите, может такая фича быть в С++next как switch constexpr

yndx-antoshkka, 10 августа 2018, 16:42 Кажется её уже предлагали (вместе с for constexpr), но отправили на доработку. Скорее всего где-то в районе C++23 появится

apolukhin commented 3 years ago

Работа над идеей идёт в https://wg21.link/p1371 Мы можем помочь разве что советом