История изменений
Исправление Siborgium, (текущая версия) :
Вынужден активно применять std::visit совместно с трюком overloadded (потому, что остальные способы работы с std::variant сильно хуже)
Речь не только о std::variant
, а об сопоставлении с образцом практически произвольных типов данных.
Выглядит это в коде так себе: и излишне многословно, и читать приходится чуть-ли не задом наперед.
Не понял, что вы имеете в виду под «чуть-ли не задом наперед». Да, символов получается несколько больше, но, из моего опыта, не в 2 и более раза.
С++ можно условно разделить на два уровня. Базовый язык – (за вычетом некоторых расхождений) С (возможно, с классами), и ++ сверху. Отношение достаточно сильно напоминает отношение TS и JS.
В С++ есть сопоставление с образцом, оно крайне развито и постоянно используется – это сопоставление с образцом при выборе перегрузки из overload set. В С++20, с появлением концептов, оно стало полноправным членом языка – SFINAE не имело своего синтаксиса, и было откровенно уродливым.
В «С» сопоставления с образцом нет.
Предлагаемый в данном пропозале паттерн матчинг реализует исключительно «С»-шный паттерн матчинг. Он не будет работать на том уровне, на котором работает «++». Невозможно будет писать код, который будет брать шаблонный код и сопоставлять его с шаблонным кодом.
С++ перегружен фичами, которые плохо взаимодействуют друг с другом. Их нельзя будет просто убрать, если они плохо себя зарекомендуют.
Этот пропозал добавляет новый синтаксис – во многих местах ломающий совместимость – буквально для всего подряд. При этом он не предлагает почти ничего, чего нельзя было бы реализовать средствами языка, по сути являясь синтаксическим сахаром. Наконец, этот сахар завязывается на чисто библиотечные элементы языка – T::index()
, что еще ухудшает его позиции.
При этом паттерн-матчинг над «С» достаточно просто реализуется средствами «++». Здесь уже был топик с примером того, как просто реализовать сопоставление с образцом. Я не буду сейчас его искать, но приведу код, который писал сам какое-то время назад.
// примитив для compile-time строк
template <std::size_t N>
struct string_lit {
constexpr string_lit(const char (&s)[N]) {
std::copy_n(s, N, str);
}
constexpr bool operator == (std::string_view view) const {
return std::string_view{ str } == view;
}
char str[N];
};
template <string_lit word>
constexpr auto on_(auto && f) {
return [=](std::string_view sample) -> bool {
auto matches = word == sample;
if (matches) {
f();
}
return matches;
};
};
constexpr auto else_(auto && f) {
return [=](auto _) { f(); return true; };
};
void match(std::string_view sample, auto && try1) {
try1(sample);
}
void match(std::string_view sample, auto && try1, auto && ... tries) {
if (!try1(sample)) {
match(sample, std::forward<decltype(tries)>(tries)...);
}
}
Этих 40 строк уже достаточно для того, чтобы писать
match(
sample,
on_<"ABC">([&]() { ... },
on_<"CDE">([&]() { ... },
else_([&](){ ... })
)
без каких-либо пропозалов, этот код легко расширяется до произвольным значений и типов и взаимодействует с любыми существующими языковыми фичами.
В контексте всего выше сказанного, я не вижу смысла в пропозале, реализующем чисто синтаксический сахар ценой внесения нового «языка в себе». Значительно более ценным пропозалом была бы рефлексия – она еще и действительно реализована, в отличие от этого пропозала.
Исправление Siborgium, :
Вынужден активно применять std::visit совместно с трюком overloadded (потому, что остальные способы работы с std::variant сильно хуже)
Речь не только о std::variant
, а об сопоставлении с образцом практически произвольных типов данных.
Выглядит это в коде так себе: и излишне многословно, и читать приходится чуть-ли не задом наперед.
Не понял, что вы имеете в виду под «чуть-ли не задом наперед». Да, символов получается несколько больше, но, из моего опыта, не в 2 и более раза.
С++ можно условно разделить на два уровня. Базовый язык – (за вычетом некоторых расхождений) С (возможно, с классами), и ++ сверху. Отношение достаточно сильно напоминает отношение TS и JS.
В С++ есть сопоставление с образцом, оно крайне развито и постоянно используется – это сопоставление с образцом при выборе перегрузки из overload set. В С++20, с появлением концептов, оно стало полноправным членом языка – SFINAE не имело своего синтаксиса, и было откровенно уродливым.
В «С» сопоставления с образцом нет.
Предлагаемый в данном пропозале паттерн матчинг реализует исключительно «С»-шный паттерн матчинг. Он не будет работать на том уровне, на котором работает «++». Невозможно будет писать код, который будет брать шаблонный код и сопоставлять его с шаблонным кодом.
С++ перегружен фичами, которые плохо взаимодействуют друг с другом. Их нельзя будет просто убрать, если они плохо себя зарекомендуют.
Этот пропозал добавляет новый синтаксис – во многих местах ломающий совместимость – буквально для всего подряд. При этом он не предлагает почти ничего, чего нельзя было бы реализовать средствами языка, по сути являясь синтаксическим сахаром. Наконец, этот сахар завязывается на чисто библиотечные элементы языка – T::index()
, что еще ухудшает его позиции.
При этом паттерн-матчинг над «С» достаточно просто реализуется средствами «++». Здесь уже был топик с примером того, как просто реализовать сопоставление с образцом. Я не буду сейчас его искать, но приведу код, который писал сам какое-то время назад.
// примитив для compile-time строк
template <std::size_t N>
struct string_lit {
constexpr string_lit(const char (&s)[N]) {
std::copy_n(s, N, str);
}
constexpr bool operator == (std::string_view view) const {
return std::string_view{ str } == view;
}
char str[N];
};
template <string_lit word>
constexpr auto on_(auto && f) {
return [=](std::string_view sample) -> bool {
auto matches = word == sample;
if (matches) {
f();
}
return matches;
};
};
constexpr auto else_(auto && f) {
return [=](auto _) { f(); return true; };
};
void match(std::string_view sample, auto && try1) {
try1(sample);
}
void match(std::string_view sample, auto && try1, auto && ... tries) {
if (!try1(sample)) {
match(sample, std::forward<decltype(tries)>(tries)...);
}
}
Этих 40 строк уже достаточно для того, чтобы писать
match(
sample,
on_<"ABC">([&]() { ... },
on_<"CDE">([&]() { ... },
else_([&](){ ... })
)
без каких-либо пропозалов, легко расширяется до произвольным значений и типов и взаимодействует с любыми существующими языковыми фичами.
В контексте всего выше сказанного, я не вижу смысла в пропозале, реализующем чисто синтаксический сахар ценой внесения нового «языка в себе». Значительно более ценным пропозалом была бы рефлексия – она еще и действительно реализована, в отличие от этого пропозала.
Исходная версия Siborgium, :
Вынужден активно применять std::visit совместно с трюком overloadded (потому, что остальные способы работы с std::variant сильно хуже)
Речь вовсе не про std::variant
, а об сопоставлении с образцом практически произвольных типов данных.
Выглядит это в коде так себе: и излишне многословно, и читать приходится чуть-ли не задом наперед.
Не понял, что вы имеете в виду под «чуть-ли не задом наперед». Да, символов получается несколько больше, но, из моего опыта, не в 2 и более раза.
С++ можно условно разделить на два уровня. Базовый язык – (за вычетом некоторых расхождений) С (возможно, с классами), и ++ сверху. Отношение достаточно сильно напоминает отношение TS и JS.
В С++ есть сопоставление с образцом, оно крайне развито и постоянно используется – это сопоставление с образцом при выборе перегрузки из overload set. В С++20, с появлением концептов, оно стало полноправным членом языка – SFINAE не имело своего синтаксиса, и было откровенно уродливым.
В «С» сопоставления с образцом нет.
Предлагаемый в данном пропозале паттерн матчинг реализует исключительно «С»-шный паттерн матчинг. Он не будет работать на том уровне, на котором работает «++». Невозможно будет писать код, который будет брать шаблонный код и сопоставлять его с шаблонным кодом.
С++ перегружен фичами, которые плохо взаимодействуют друг с другом. Их нельзя будет просто убрать, если они плохо себя зарекомендуют.
Этот пропозал добавляет новый синтаксис – во многих местах ломающий совместимость – буквально для всего подряд. При этом он не предлагает почти ничего, чего нельзя было бы реализовать средствами языка, по сути являясь синтаксическим сахаром. Наконец, этот сахар завязывается на чисто библиотечные элементы языка – T::index()
, что еще ухудшает его позиции.
При этом паттерн-матчинг над «С» достаточно просто реализуется средствами «++». Здесь уже был топик с примером того, как просто реализовать сопоставление с образцом. Я не буду сейчас его искать, но приведу код, который писал сам какое-то время назад.
// примитив для compile-time строк
template <std::size_t N>
struct string_lit {
constexpr string_lit(const char (&s)[N]) {
std::copy_n(s, N, str);
}
constexpr bool operator == (std::string_view view) const {
return std::string_view{ str } == view;
}
char str[N];
};
template <string_lit word>
constexpr auto on_(auto && f) {
return [=](std::string_view sample) -> bool {
auto matches = word == sample;
if (matches) {
f();
}
return matches;
};
};
constexpr auto else_(auto && f) {
return [=](auto _) { f(); return true; };
};
void match(std::string_view sample, auto && try1) {
try1(sample);
}
void match(std::string_view sample, auto && try1, auto && ... tries) {
if (!try1(sample)) {
match(sample, std::forward<decltype(tries)>(tries)...);
}
}
Этих 40 строк уже достаточно для того, чтобы писать
match(
sample,
on_<"ABC">([&]() { ... },
on_<"CDE">([&]() { ... },
else_([&](){ ... })
)
без каких-либо пропозалов, легко расширяется до произвольным значений и типов и взаимодействует с любыми существующими языковыми фичами.
В контексте всего выше сказанного, я не вижу смысла в пропозале, реализующем чисто синтаксический сахар ценой внесения нового «языка в себе». Значительно более ценным пропозалом была бы рефлексия – она еще и действительно реализована, в отличие от этого пропозала.