cpp-ru / ideas

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

pattern matching or partial specialization for using type definitions and for inline variables #345

Closed apolukhin closed 3 years ago

apolukhin commented 3 years ago

Перенос предложения: голоса +0, -4 Автор идеи: post-increment

При написании трейтов часто приходится писать специализации используя технику частичной специализации шаблона. По сути - это паттерн-матчинг использующий средства языка, но требующий дополнительного кода. А что, если позволить нечто схожее определению функций в Haskell? Примеры ниже.

Допустим, мы хотим написать банальный "трейт" для своих типов. Например, best_floating_point_t. Первый вариант это писать класс best_floating_point и специализировать его для каждого особого случая. А далее уже использовать using для определения best_floating_point_t. Должно выглядеть примерно так

template<typename T>
best_floating_point_t = typename best_floating_point<T>::type;

Предлагается сделать возможным такой синтаксис:

template<typename T> 
using best_floating_point_t = some_default_case;
//specializations
template<> using best_floating_point_t<int> = float;
template<> using best_floating_point_t<long> = double;
template<> using best_floating_point_t<some_user_type> = double;

Аналоично можно сделать для inline variables:

template<typename T>
inline const std::string type_name = "unknown";

template<> inline const std::string type_name<int> = "int";
template<> inline const std::string type_name<double> = "double";
apolukhin commented 3 years ago

Andrey Davydov, 27 августа 2018, 12:36 Для template variables специализация возможно уже сейчас -- ровно ваш пример будет компилироваться и работать.

Для template type alias специализация это плохая идея, она противоречит смыслу template type alias'а, а именно, то что он не самостоятельная сущность, а всего лишь alias. В частности, в стандарте приведен следующий пример:

template<class T> struct Alloc { /* ... */ };
template<class T> using Vec = vector<T, Alloc<T>>;

Vec<int> v; // same as vector<int, Alloc<int>> v;

template<class T>
  void process(Vec<T>& v)
  { /* ... */ }

template<class T>
  void process(vector<T, Alloc<T>>& w)
  { /* ... */ } // error: redefinition