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

Игорь Шаповал
Игорь Шаповал

В С++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;
}
11
рейтинг
14 комментариев
Sasha Sitnikov
	case 2:
		result = (name);

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

Sasha Sitnikov
Игорь Шаповал

Сори, переменная result должна быть типа decltype(auto)

decltype(auto) result;
Игорь Шаповал
Sasha Sitnikov

Игорь Шаповал, то есть, за одно добавить еще и deferred type deduction? Это само по себе не маленькое изменение

Sasha Sitnikov
Andrey

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

Andrey
Игорь Шаповал

Пример с get() работает. Использовал structured bindings в проекте для класса.

Игорь Шаповал
Andrey

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

Andrey
Игорь Шаповал

Но согласитесь было бы классно иметь такую фичу в языке. 

Игорь Шаповал
dreverser

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

 

dreverser
Саша Зайцев

dreverser, вот Вы смеётесь, а всё ведь к этому и идёт...

Саша Зайцев
yndx-antoshkka

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

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

yndx-antoshkka
dreverser

так я и говорю, бросайте по 1/100 языка втягивать в constexpr

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

dreverser
yndx-antoshkka

Слона надо есть по кускам, иначе он не помещается в рот... Сделать одним махом всё constexpr не получится - подобное предложение будет перевариваться в комитете десятилетия.

yndx-antoshkka
Игорь Шаповал

yndx-antoshkka Скажите, может такая фича быть в С++next как switch constexpr

Игорь Шаповал
yndx-antoshkka

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

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