Pull to refresh
2
Андрей Давыдов@AndDav

Пользователь

Send message
Я ничего не слышал про планы на variadic generics.
Я просто загуглил и нашел такой pre-RFC. Возможно, дальше этого дело не пошло, я не в курсе.
Но, даже если бы variadic generics были, я сомневаюсь, чтобы они помогли в данной ситуации, ведь они оперируют на уровне сигнатуры типов, а не сигнатуры аргументов функции.
Ну если variadic generics случатся, то написать функцию принимающую переменное число аргументов не должно быть проблемой (сужу по опыту C++).
А в чём проблема использования макросов?
Наверное, в использовании нет проблем (у меня нет практического опыта на Rust-е). Я думал про написание такого макроса — оперировать потоком токенов должно быть сложнее, чем написание generic функции.

Спасибо, понятно. Я так понимаю, что variadic generics есть в долгосрочных планах и они заменят в будущем такого рода использование макросов?

А почему join макрос? Разве функцией он не реализуется?

Можно задействовать и свой компаратор и стандартный std::less<void>, но это надо делать явно, я же говорил о том, что комитет решил не делать это поведением по умолчанию std::{set,map} чтобы не ломать ABI.
И этот самый template<class K> iterator find(const K& x) не помогает избежать создания временной строки при вызове s.find("very very long string") из моего первого примера так как less<string> все равно ожидает 2 аргумента типа string.
В каком случае в моем примере был бы сломан API? Весь код, компилирующийся в предположении, что set<T> это set<T, less<T>>, продолжит компилироваться если set<T> станет set<T, less<void>>.
Хочется привести хоть один реальный пример, когда комитет отказался менять API на потенциально более производительное ради сохранения ABI.
std::set<std::string> s = ...;
s.find("very very long string"); // конструирование std::string здесь

Если бы после появления std::less<void> в C++14 определение std::set поменяли с
template<class Key, class Compare = less<Key>, ...>
class set {...};
на
template<class Key, class Compare = less<void>, ...>
class set {...};
предыдущий пример не требовал бы создание временной std::string, но это сломало бы ABI.
Блин. А транскрипт есть?
Как ни странно, даже есть: habr.com/ru/company/jugru/blog/467299
Логика разная для dependent и не dependent имен. Само по себе наличие слова template не отменяет парсинг содержимого «if constexpr» и сопутствующей инстанциации шаблонов: gcc.godbolt.org/z/OC6keb.
Да, первая часть вашего утверждения верна. Посколько в C++ парсинг зависит от резолва, до без инстанциации шаблонов, код распарсить невозможно, не важно при этом под `if constexpr (false)` он или нет.
template<typename> struct X {
  using type_or_value = int;
};

void f() {
  if constexpr (false)
    int a(X<int>::type_or_value);
}

template<typename T>
void g() {
  if constexpr (requires { X<T>::type_or_value; })
    int b(X<T>::type_or_value);
}

g<float>();

В функции f компилятор при парсинге чтобы определить является ли `a` переменной или функцией проинстанцирует `X`. При парсинге тела `g` компилятор решил, что `b` это переменная (мы не написали typename перед X::type_or_value) так, что если бы при инстанцировании `g` компилятор бы стал инстанцировать then branch if-а (несмотря на то, что в условии написано, что он работает только когда X::type_or_value это expression), случился бы конфуз.
Вы согласны с тем, что код под `if constexpr (false)` нужно хотя бы попарсить? Если да, то ваша фраза «нет сложности в том, чтобы отстрелить генерацию кода или инсталляцию шаблонов» не верна, для парсинга уже может быть нужно инстанцировать шаблоны.
Потому что resolve и template instantiation в C++ неразрывно связаны. Если хочется проверить синтаксическую корректность кода, то шаблонов инстанцировать придется, классический пример:
int x(template_class<int>::type_or_value);
Материал интересный и написано живописно, но при прочтении статьи возникают два ложных ощущения:
  • эта техника может использоваться только во вред, у нее нет никаких полезных применений;
  • комитет по стандартизации не собирается никак решать проблему stateful metaprogramming, ограничившись порицанием программистов ее использующих.

Концепты образуют частичный порядок (partial ordering, subsumption), что позволяет удобно перегружать функции, к примеру, std::distance для разных категорий итераторов.
Концепты образуют частичный порядок (partial ordering, subsumption), что позволяет удобно перегружать функции, к примеру, std::distance для разных категорий итераторов.
Определенный таким образом enable_if_t и пара таких функций f заставляют компиляторы вести себя неадекватно. К примеру GCC и Clang согласны в том, что это 2 декларации одной функции: https://gcc.godbolt.org/z/jBRf-G, и при этом вызов f() Clang компилирует, а GCC — нет: https://gcc.godbolt.org/z/N2Ohe4.
Подробнее о том как equivalent, but functionally not equivalent функции сводят компилятор с ума можно посмотреть тут: www.youtube.com/watch?v=udTEfwCkmaw&t=2520s

Information

Rating
Does not participate
Registered
Activity