std::optional ~ как value-параметр шаблона
От: Sm0ke Россия ksi
Дата: 05.08.23 14:25
Оценка:
Есть стандартный optional, который constexpr
Попробуем взять его подставить как value param шаблона

#include <optional>
#include <cstddef>

template <std::optional<std::size_t> Size>
struct omg {};


Ошибка компиляции!

msvc ~
error C2993: 'std::optional<unsigned __int64>': is not a valid type for non-type template parameter 'Size'
message : '_Optional_construct_base<unsigned __int64>' is not a public base class

gcc ~
error: 'std::optional<long unsigned int>' is not a valid type for a template non-type parameter because it is not structural
/opt/compiler-explorer/gcc-13.1.0/include/c++/13.1.0/optional:705:11: note: base class 'std::_Optional_base<long unsigned int, true, true>' is not public


---

Я попробовал накидать минимальный велосипедный optional с constexpr
И подставить его как параметр шаблона...
Получилось!

https://godbolt.org/z/sboqbPcTW

Но есть как минимум два нюанса:
1. Этот optional Пока только для скалярного типа T (Думаю, что для остальных типов доделать специализацию является возможным)
2. Все свойства public:

Второй момент не очень приятный. Такую штуку можно будет использовать unsafe.
Если же свойства скрыть, то тип нельзя будет подставить как параметр шаблона.

Как сделать, чтобы было красиво? Неужели придётся смириться со вторым?
Отредактировано 05.08.2023 14:47 Sm0ke . Предыдущая версия .
Re: std::optional ~ как value-параметр шаблона
От: sergii.p  
Дата: 07.08.23 12:46
Оценка: +1
Здравствуйте, Sm0ke, Вы писали:

S>Как сделать, чтобы было красиво? Неужели придётся смириться со вторым?


тяжело что-то советовать когда не понятно что надо получить в конце. Можно попробовать сделать на вариадиках

template <std::size_t... Size>
struct omg {};


ну и дальше уже обрабатывать ситуацию когда sizeof...(Size) == 0

для пользователя всё выглядит даже круче чем через nullopt_t

omg<> empty;
omg<10> non_empty;
Re: std::optional ~ как value-параметр шаблона
От: Chorkov Россия  
Дата: 07.08.23 14:38
Оценка: 12 (1)
Здравствуйте, Sm0ke, Вы писали:

S>Как сделать, чтобы было красиво? Неужели придётся смириться со вторым?


Я бы использовал auto — параметр шаблона:

template <auto Size>
struct omg {
    static_assert(( std::is_convertible_v<decltype(Size), std::optional<std::size_t> > ));
    static constexpr std::optional<std::size_t> size={Size}; // используем так, как хотели бы использовать параметр шаблона.
  
    //...
};

omg<123> a;
omg<std::nullopt> b;
Re[2]: std::optional ~ как value-параметр шаблона
От: Sm0ke Россия ksi
Дата: 08.08.23 12:52
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>
SP>template <std::size_t... Size>
SP>struct omg {};
SP>


SP>ну и дальше уже обрабатывать ситуацию когда sizeof...(Size) == 0


SP>для пользователя всё выглядит даже круче чем через nullopt_t


SP>
SP>omg<> empty;
SP>omg<10> non_empty;
SP>


Отлично, спасибо!

template <std::size_t ... Size>
requires ( sizeof...(Size) < 2 )
struct omg {};
Re[2]: std::optional ~ как value-параметр шаблона
От: Sm0ke Россия ksi
Дата: 08.08.23 13:02
Оценка: 105 (1)
Здравствуйте, Chorkov, Вы писали:

C>Я бы использовал auto — параметр шаблона:


C>
C>template <auto Size>
C>struct omg {
C>    static_assert(( std::is_convertible_v<decltype(Size), std::optional<std::size_t> > ));
C>    static constexpr std::optional<std::size_t> size={Size}; // используем так, как хотели бы использовать параметр шаблона.
  
C>    //...
C>};

C>omg<123> a;
C>omg<std::nullopt> b;

C>


Даже лучше предыдущего reply-я с вариадиком, т:к таких параметров может быть несколько.
Переделал на концепт:

#include <cstddef>
#include <type_traits>
#include <optional>

template <typename T, typename ... U>
concept c_any_of = (std::is_same_v<T, U> || ...);

template <c_any_of<std::size_t, std::nullopt_t> auto Size>
struct omg {};

int main() {
  omg<std::nullopt> var1;
  omg<10zu> var2;
  return 0;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.