выделить тип из optional который сам template type
От: The Passenger Голландия  
Дата: 01.02.24 15:20
Оценка:
Что надо — функция которая может принимать ссылку на некий темплейт
темплейт может быть как простым типом типа инта или дубля, я может быть optional для простых типов ... но они тоже могут быть разные

1. Как определить что тип optional?
2. Как вычленить тип из optional?

Можно решить это в лоб перегрузкой, но хочеться красиво ... хотя может перегрузкой может получиться красивее

Спасибки
Весь мир — Кремль, а люди в нем — агенты
Re: выделить тип из optional который сам template type
От: sergii.p  
Дата: 01.02.24 15:48
Оценка:
Здравствуйте, The Passenger, Вы писали:

TP>Можно решить это в лоб перегрузкой, но хочеться красиво ... хотя может перегрузкой может получиться красивее


ничего не понял. Что может быть красивее и лаконичнее специализации?

template <typename T> void foo(const T& ) {
}

template <typename T> void foo(const std::optional<T>& ) {
}
Re[2]: выделить тип из optional который сам template type
От: reversecode google
Дата: 01.02.24 15:57
Оценка:
он хочет с как минимум c enable_if
а для этого надо хотя бы 11 знать
вот и хочет что бы за него

хотя пример в гугле третий линк сверху
Re[2]: выделить тип из optional который сам template type
От: The Passenger Голландия  
Дата: 01.02.24 18:52
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>ничего не понял. Что может быть красивее и лаконичнее специализации?


в принципе тоже норм, я думал о чем то типа

if constexpr ( is_optional<T>::value )


не столько для кода сколько для расширения кругозора
ну нет так нет

нашел такое, но не сильно красиво, да еще и надо тип выковыривать как-то

https://topanswers.xyz/cplusplus?q=793#a932

хотя тип можно выковырять через T::value_type ... но все равно суммарно получается длиннее и непонятнее чем просто перегрузка
Весь мир — Кремль, а люди в нем — агенты
Отредактировано 01.02.2024 19:23 The Passenger . Предыдущая версия . Еще …
Отредактировано 01.02.2024 19:08 The Passenger . Предыдущая версия .
Отредактировано 01.02.2024 19:06 The Passenger . Предыдущая версия .
Re: выделить тип из optional который сам template type
От: rg45 СССР  
Дата: 01.02.24 21:27
Оценка: 9 (3) +1
Здравствуйте, The Passenger, Вы писали:

TP>1. Как определить что тип optional?


Можно даже в более общем виде — определить, является ли некий произвольный тип воплощением произвольно заданного шаблона:

http://coliru.stacked-crooked.com/a/9c144654296f4337

template <typename, template <typename...> class> struct is_instance_of : std::false_type {};
template <template <typename...> class T, typename...X> struct is_instance_of<T<X...>, T> : std::true_type {};
template <typename T, template <typename...> class TT> concept instance_of = is_instance_of<std::decay_t<T>, TT>::value;

static_assert(instance_of<std::optional<int>, std::optional>);
static_assert(instance_of<std::string, std::basic_string>);
static_assert(instance_of<std::map<int, double>, std::map>);


Если std::optional представляет особый интерес, можно определить более специальный инструмент на основе общего:

template <typename T> concept instance_of_optional = std::instance_of<T, std::optional>;

static_assert(instance_of_optional<std::optional<int>>);


Понятное дело, можно обойтись и без концептов, привычными метафункциями:

template <typename T, template <typename...> class TT> constexpr bool is_instance_of_v = is_instance_of<std::decay_t<T>, TT>::value;
template <typename T> constexpr bool is_optional_v = std::is_instance_of_v<T, std::optional>;


TP>2. Как вычленить тип из optional?


Общий подход такой:

template <instance_of<std::optional>> struct optional_underlying;
template <typename T> struct optional_underlying<std::optional<T>> { using type = T; };

template <instance_of<std::optional> T>
using optional_underlying_t = typename optional_underlying<T>::type;

Но менно для std::optional можно просто вытащить вложенное имя типа:

template <instance_of<std::optional> T>
using optional_underlying_t = typename T::value_type;


TP>Можно решить это в лоб перегрузкой, но хочеться красиво ... хотя может перегрузкой может получиться красивее


Если простая перегрузка подходит, то, имхо, это самый оптимальный вариант. Еще варианты:

1. Использовать концепт, определенный выше (C++20 и выше):

template <instance_of<std::optional> T>
void foo(T&&) { /* . . .*/ }


2. Старый добрый SFINAE:

template <typename T, std::enable_if_t<is_instance_of<T, std::optional>::value, int> = 0>
void foo(T&&) { /* . . .*/ }


3. if constexpr — это вариант ты знаешь.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 02.02.2024 14:29 rg45 . Предыдущая версия . Еще …
Отредактировано 02.02.2024 14:24 rg45 . Предыдущая версия .
Отредактировано 02.02.2024 14:01 rg45 . Предыдущая версия .
Отредактировано 02.02.2024 13:26 rg45 . Предыдущая версия .
Отредактировано 02.02.2024 11:15 rg45 . Предыдущая версия .
Отредактировано 02.02.2024 10:19 rg45 . Предыдущая версия .
Отредактировано 02.02.2024 10:17 rg45 . Предыдущая версия .
Отредактировано 02.02.2024 10:05 rg45 . Предыдущая версия .
Отредактировано 02.02.2024 9:58 rg45 . Предыдущая версия .
Отредактировано 01.02.2024 22:38 rg45 . Предыдущая версия .
Отредактировано 01.02.2024 22:06 rg45 . Предыдущая версия .
Отредактировано 01.02.2024 22:03 rg45 . Предыдущая версия .
Отредактировано 01.02.2024 21:59 rg45 . Предыдущая версия .
Отредактировано 01.02.2024 21:55 rg45 . Предыдущая версия .
Отредактировано 01.02.2024 21:53 rg45 . Предыдущая версия .
Отредактировано 01.02.2024 21:53 rg45 . Предыдущая версия .
Отредактировано 01.02.2024 21:41 rg45 . Предыдущая версия .
Отредактировано 01.02.2024 21:40 rg45 . Предыдущая версия .
Отредактировано 01.02.2024 21:33 rg45 . Предыдущая версия .
Отредактировано 01.02.2024 21:33 rg45 . Предыдущая версия .
Re: выделить тип из optional который сам template type
От: Кодт Россия  
Дата: 04.02.24 21:17
Оценка: 4 (1)
Здравствуйте, The Passenger, Вы писали:

TP>Что надо — функция которая может принимать ссылку на некий темплейт

TP>темплейт может быть как простым типом типа инта или дубля, я может быть optional для простых типов ... но они тоже могут быть разные

Самое главное: а что дальше хочется с этим сделать?
Эта функция должна как-то единообразно работать и с optional, и с обычными? Или там есть какое-то ветвление?

(здесь и далее пишу без ссылок и форвардов, чтобы не засорять иллюстрацию)

Тупое решение
template<class T> void foo(T v) { .....(v) }
template<class T> void foo(optional<T> p) { .....(!p, *p) }


Обобщаем монады Id и Maybe чисто по месту
template<class T> void foo_to_be_lifted(T v) { ....(v) }

template<class T> void foo(T v) { foo_to_be_lifted(v); }
template<class T> void foo(optional<T> p) { if(p) foo_to_be_lifted(*p); else ..... };


Улучшаем Id до Maybe
template<class P> void foo_already_lifted(P p) { .....(!p, *p) }  // аргумент - указателеподобный

template<class T> void foo(T v) { foo_already_lifted(&v); }  // заведомо ненулевой
template<class T> void foo(optional<T> p) { foo_already_lifted(p); }  // возможно нулевой


Если такого кода много, пишем функцию высшего порядка
template<class F, class T> void lift_and_run(F f, T v) { f(v); }
template<class F, class T> void lift_and_run(F f, optional<T> p) { assert(p); f(*p); }  // ну или как обрабатывать !p ?

template<class F, class T> void run_lifted(F f, T v) { f(&v); }
template<class F, class T> void run_lifted(F f, optional<T> p) { f(p); }

// и даже можем просто поднимать функции
auto lift(F f) { return [f](auto arg) { lift_and_run(f, arg); }; }
auto lifted(F f) { return [f](auto arg) { run_lifted(f, arg); }; }


Можем единообразно поднимать аргумент, а функция пусть будет ad-hoc
template<class T> auto as_optional(T& v) { return &v; }  // ну, тут уж ссылка пролезла в иллюстрацию
template<class T> auto as_optional(optional<T> p) { return p; }

// и кстати, этой функцией можно воспользоваться для поднятия-опускания типа
template<class XZ> using add_optional_t = decltype(as_optional(declval<XZ>()));
template<class XZ> using remove_optional_t = remove_ref_t<decltype(*as_optional(declval<XZ>()))>;

template<class XZ> void foo(XZ arg) {
  auto p = as_optional(arg);
  .....(!p, *p)  // дальше всё как с optional
}

template<class XZ> void bar(XZ arg) {
  auto p = as_optional(arg);
  .....(!p, *p)
}


Вообще можно упороться по поводу труъ хаскельных функторов и монад — сделать fmap, переупаковывать optional<optional<T>> в optional<T>, вот это вот всё...
Сейчас полночь с воскресенья на понедельник, я не особо заботился о строгости проекции плюсов на хаскелл и обратно, просто идею набросил.
Хотя проекция тут очевидна и напрашивается.
Глубина кроличьей норы — на усмотрение тебя, Нео, а я Морфей, у меня лапки, и в каждой лапке по таблетке: одна со снотворным, другая со слабительным.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.