Количество аргументов функции как параметр шаблона
От: Went  
Дата: 12.04.17 09:45
Оценка:
Здравствуйте. Допустим есть шаблон:
template<typename T, size_t S>
struct Vector
{
  void set(...);
};

Что я должен написать вместо троеточия, чтобы количество аргументов, принимаемое функцией set было равно аргументу шаблона S? Я, конечно, могу написать там parameter pack и проверить sizeof... через static_assert, но хочется чтобы красиво, и неверных перегрузок просто не существовало. Ну и грядок enable_if тоже не хочется.
Re: Количество аргументов функции как параметр шаблона
От: niXman Ниоткуда https://github.com/niXman
Дата: 12.04.17 10:06
Оценка:
http://coliru.stacked-crooked.com/a/26310b85c2490e9f
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: Количество аргументов функции как параметр шаблона
От: niXman Ниоткуда https://github.com/niXman
Дата: 12.04.17 10:12
Оценка: 6 (1) +1
похоже, я неправильно понял задачу...

enable_if, имхо, самый разумный вариант...
http://coliru.stacked-crooked.com/a/a76bf9f72a67b833
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Отредактировано 12.04.2017 10:15 niXman . Предыдущая версия .
Re: Количество аргументов функции как параметр шаблона
От: N. I.  
Дата: 12.04.17 11:18
Оценка: 17 (3)
Went:

W>Что я должен написать вместо троеточия, чтобы количество аргументов, принимаемое функцией set было равно аргументу шаблона S? Я, конечно, могу написать там parameter pack и проверить sizeof... через static_assert, но хочется чтобы красиво, и неверных перегрузок просто не существовало. Ну и грядок enable_if тоже не хочется.


Без наследования это, скорее всего, невозможно. С помощью наследования от специализированных шаблонов такое можно провернуть, но подобные финты будут явно посложнее enable_if и не очень-то красивыми: http://coliru.stacked-crooked.com/a/b22515b132b1aa2d
Re[2]: Количество аргументов функции как параметр шаблона
От: Went  
Дата: 12.04.17 12:51
Оценка:
Здравствуйте, niXman, Вы писали:

X>http://coliru.stacked-crooked.com/a/26310b85c2490e9f

Спасибо, но это — решение наоборот. Мне нужно по заранее известному параметру класса указать количество аргументов функции-члена.
Re[2]: Количество аргументов функции как параметр шаблона
От: Went  
Дата: 12.04.17 12:53
Оценка: +1 :)
Здравствуйте, niXman, Вы писали:
X>enable_if, имхо, самый разумный вариант...
X>http://coliru.stacked-crooked.com/a/a76bf9f72a67b833
Спасибо! Отличное решение! Такого способа использовать enable_if я не придумал Я предполагал кучу перегрузок, из которых отключаются все кроме одной, но это решение весьма элегантно.
Re[2]: Количество аргументов функции как параметр шаблона
От: Went  
Дата: 12.04.17 14:50
Оценка:
Здравствуйте, niXman, Вы писали:

X>enable_if, имхо, самый разумный вариант...

X>http://coliru.stacked-crooked.com/a/a76bf9f72a67b833
Кстати, 2013-ый вижуал это не варит, говорит, что type у enable_if не определен. Выходит, у него SFINAE сбоит или что-то из стандарта не реализовано?
Re[3]: Количество аргументов функции как параметр шаблона
От: niXman Ниоткуда https://github.com/niXman
Дата: 12.04.17 14:53
Оценка:
попробуй так: http://coliru.stacked-crooked.com/a/7137177cccfd4d0d
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[4]: Количество аргументов функции как параметр шаблона
От: Went  
Дата: 12.04.17 17:24
Оценка:
Здравствуйте, niXman, Вы писали:
X>попробуй так: http://coliru.stacked-crooked.com/a/7137177cccfd4d0d
то же самое
Re[2]: Количество аргументов функции как параметр шаблона
От: rg45 СССР  
Дата: 12.04.17 19:02
Оценка: 21 (2)
Здравствуйте, N. I., Вы писали:

NI>Без наследования это, скорее всего, невозможно. С помощью наследования от специализированных шаблонов такое можно провернуть, но подобные финты будут явно посложнее enable_if и не очень-то красивыми: http://coliru.stacked-crooked.com/a/b22515b132b1aa2d


Не так уж плох этод подход, имхо. Во-первых потому, что получить размер из пака типов значительно проще, чем пак типов из размера. Во-вторых потому, что этот пак типов будет нужен постоянно, как я догадываюсь, и то, что он есть всегда под рукой должно упростить определение внутренностей вектора, обеспечить строгость в соблюдении соответствия типов.

Пара корректировок по коду. Реализацию gen_type_pack можно слегка упростить использованием std::index_sequence:

http://ideone.com/3l0Bso
template <typename, typename> struct gen_type_pack_;
template <typename T, size_t...i>
struct gen_type_pack_<T, std::index_sequence<i...>>
{
    template <size_t> using element = T;
    using type = type_pack<element<i>...>;
};
 
template <typename T, size_t N>
using gen_type_pack = typename gen_type_pack_<T, std::make_index_sequence<N>>::type;


При этом сам vector имеет смысл сделать простым алиасом vector_base, подобно тому, как std::string является алиасом std::basic_string:
template <class T, std::size_t N>
using vector = vector_base<gen_type_pack<T, N>>;


Таким образом избавляемся от наследования, получаем единый класс реализации, не плодим избыточные сущности.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 13.04.2017 5:43 rg45 . Предыдущая версия . Еще …
Отредактировано 13.04.2017 5:39 rg45 . Предыдущая версия .
Отредактировано 12.04.2017 19:59 rg45 . Предыдущая версия .
Отредактировано 12.04.2017 19:56 rg45 . Предыдущая версия .
Отредактировано 12.04.2017 19:23 rg45 . Предыдущая версия .
Re[5]: Количество аргументов функции как параметр шаблона
От: niXman Ниоткуда https://github.com/niXman
Дата: 12.04.17 21:23
Оценка:
Здравствуйте, Went, Вы писали:

W>то же самое

думаю, как-то так: http://coliru.stacked-crooked.com/a/df74701ff46367f3
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[6]: Количество аргументов функции как параметр шаблона
От: rg45 СССР  
Дата: 12.04.17 21:38
Оценка:
Здравствуйте, niXman, Вы писали:

X>думаю, как-то так: http://coliru.stacked-crooked.com/a/df74701ff46367f3


template<typename T, std::size_t S>
struct vector {
    template<typename... U>
    typename std::enable_if<sizeof...(U) == S>::type
    set(U... args) {}
};


Тут вот ведь какая штука, если я правильно понимаю задумку, никакие другие типы, кроме T эта функция принимать не должна.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[7]: Количество аргументов функции как параметр шаблона
От: Went  
Дата: 13.04.17 06:52
Оценка:
Здравствуйте, rg45, Вы писали:
R>Тут вот ведь какая штука, если я правильно понимаю задумку, никакие другие типы, кроме T эта функция принимать не должна.
Ну, вообще-то, да.
Re[8]: Количество аргументов функции как параметр шаблона
От: rg45 СССР  
Дата: 13.04.17 09:09
Оценка:
Здравствуйте, Went, Вы писали:

R>>Тут вот ведь какая штука, если я правильно понимаю задумку, никакие другие типы, кроме T эта функция принимать не должна.

W>Ну, вообще-то, да.

Ну конечно же! В противном случае выходит, что мы организовали контроль количества параметров, пожертвовав котролем соответствия типов. Теперь при любом несоответствии типов все предупреждения и ошибки будут возникать внутри функции set, а не в клиентском коде.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: Количество аргументов функции как параметр шаблона
От: N. I.  
Дата: 13.04.17 10:17
Оценка:
rg45:

R>Пара корректировок по коду. Реализацию gen_type_pack можно слегка упростить использованием std::index_sequence:


Ну, в общем, да, то был чисто рукопашно написанный код. Правда, вспомогательные шаблоны вполне реюзабельны для других целей. Поэтому, кстати, нет особого смысла жадничать с отбрасыванием определения у type_pack. Мне, например, как-то надо было передать нечто вроде type_pack<Types...>() в шаблон функции, чтоб та вывела Types из переданного аргумента. Явно указать Types... для шаблона функции не было возможности из-за использования там ещё одного пака. Будь type_pack<Types...> неполным типом, пришлось бы передавать туда что-то наподобие (type_pack<Types...> *)nullptr, что, по-моему, несколько менее красиво, чем более простое type_pack<Types...>().

R>При этом сам vector имеет смысл сделать простым алиасом vector_base, подобно тому, как std::string является алиасом std::basic_string:

R>
R>template <class T, std::size_t N>
R>using vector = vector_base<gen_type_pack<T, N>>;
R>


R>Таким образом избавляемся от наследования, получаем единый класс реализации, не плодим избыточные сущности.


Мне трудно об этом судить без знания того, что собираются делать с этим вектором. Например, надо ли предоставить возможность использовать объявление

template <class T, std::size_t N>
    class vector;

или нужно ли определять какие-то специализации — скажем, для vector<void, 0>.
Re[4]: Количество аргументов функции как параметр шаблона
От: rg45 СССР  
Дата: 13.04.17 10:37
Оценка:
Здравствуйте, N. I., Вы писали:

NI>Будь type_pack<Types...> неполным типом, пришлось бы передавать туда что-то наподобие (type_pack<Types...> *)nullptr, что, по-моему, несколько менее красиво, чем более простое type_pack<Types...>().


std::declval<type_pack<Types...>>()?

Он же и нужен как раз при реализации всяких метафункций. Если требуется полнота, можно юзать std::tuple. Кстати, мне странно, что в стандартной библиотеке нет аналога такого вот type_pack, я уже множество раз сталкивался со случаями, когда он быд бы полезен.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[7]: Количество аргументов функции как параметр шаблона
От: niXman Ниоткуда https://github.com/niXman
Дата: 13.04.17 11:38
Оценка:
Здравствуйте, rg45, Вы писали:

R>Тут вот ведь какая штука, если я правильно понимаю задумку, никакие другие типы, кроме T эта функция принимать не должна.

запросто: http://coliru.stacked-crooked.com/a/1572113a95efa1cd

вот только метафункция std::conjunction присутствует только в С++17. посему, для msvc2013 пришлось ее скопипастить в свой код.
реализацию можно вкопипа
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[8]: Количество аргументов функции как параметр шаблона
От: rg45 СССР  
Дата: 13.04.17 12:40
Оценка:
Здравствуйте, niXman, Вы писали:

X>запросто: http://coliru.stacked-crooked.com/a/1572113a95efa1cd

X>вот только метафункция std::conjunction присутствует только в С++17. посему, для msvc2013 пришлось ее скопипастить в свой код.

А теперь конструктор

Выделить хотя бы все эти проверки в отдельную сущность, что ли:

http://coliru.stacked-crooked.com/a/f5d9c9b13476f74a
template<typename T, std::size_t S>
struct vector {

    template <typename...U>
    using IfCompatible = typename std::enable_if<sizeof...(U) == S
        && std::conjunction<std::is_same<T, std::decay_t<U>>...>::value>::type;

    template<typename...U>
    IfCompatible<U...> set(U&&...args) {}
};
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[9]: Количество аргументов функции как параметр шаблона
От: niXman Ниоткуда https://github.com/niXman
Дата: 13.04.17 12:44
Оценка:
Здравствуйте, rg45, Вы писали:

R> template <typename...U>

R> using IfCompatible = typename std::enable_if<sizeof...(U) == S

врядли msvc2013 поддерживает variable templates...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: Количество аргументов функции как параметр шаблона
От: PM  
Дата: 13.04.17 14:03
Оценка:
Здравствуйте, Went, Вы писали:

W>Здравствуйте. Допустим есть шаблон:

W>
W>template<typename T, size_t S>
W>struct Vector
W>{
W>  void set(...);
W>};
W>

W>Что я должен написать вместо троеточия, чтобы количество аргументов, принимаемое функцией set было равно аргументу шаблона S? Я, конечно, могу написать там parameter pack и проверить sizeof... через static_assert, но хочется чтобы красиво, и неверных перегрузок просто не существовало. Ну и грядок enable_if тоже не хочется.

Может быть подойдёт http://en.cppreference.com/w/cpp/utility/initializer_list
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.