Я пытаюсь определить своего рода шаблонный примитив 'map' (как в map-Reduce).Идея заключается в том, что я хочу применить функцию к каждому элементу пакета параметров шаблона.Функция может быть любым вызываемым объектом.Он может возвращать любой тип (хотя возвращаемый тип будет игнорироваться) и может принимать дополнительные аргументы поверх рассматриваемого элемента.
Сложность в том, что у меня фактически есть два пакета параметров, которые мне нужныиметь дело с.Сначала они будут упакованы вместе, но я хочу разделить их, используя специализацию шаблонов.Ниже приведена моя попытка сделать это.
Если это не очевидно (из-за ключевого слова auto в списке параметров шаблона), используется C ++ 17.
#include <utility>
template <class Signature, auto f, class... ArgsAndItems>
struct Map;
template
<
class ReturnType,
class Item,
class... ArgumentTypes,
auto f,
class... Items
>
struct Map
<
ReturnType (Item, ArgumentTypes...),
f,
ArgumentTypes...,
Item,
Items...
>
{
static void
function (ArgumentTypes &&... arguments, Item && item, Items &&... items);
};
template <class ReturnType, class Item, class... ArgumentTypes, auto f>
struct Map<ReturnType (Item, ArgumentTypes...), f, ArgumentTypes...>
{
static void
function (ArgumentTypes &&... arguments);
};
template
<
class ReturnType,
class Item,
class... ArgumentTypes,
auto f,
class... Items
>
void
Map
<
ReturnType (Item, ArgumentTypes...),
f,
ArgumentTypes...,
Item,
Items...
>::function (ArgumentTypes &&... arguments, Item && item, Items &&... items)
{
f (std::forward<Item> (item), std::forward<ArgumentTypes> (arguments)...);
Map
<
ReturnType (Item, ArgumentTypes ...),
f,
ArgumentTypes...,
Items...
>::function
(
std::forward<ArgumentTypes> (arguments)...,
std::forward<Items> (items)...
);
}
template <class ReturnType, class Item, class... ArgumentTypes, auto f>
void
Map
<
ReturnType (Item, ArgumentTypes...),
f,
ArgumentTypes...
>::function (ArgumentTypes &&... arguments)
{
}
Идея состоит в том, чтобы иметь оболочку, которая выглядит примерно так:
template <auto f, class ... ArgsAndItems>
void
map (ArgsAndItems && ... args_and_items)
{
Map
<
decltype (decltype (f)::operator ()),
f,
ArgsAndItems...
>::function (std::forward <ArgsAndItems> (args_and_items) ...);
}
, которую я бы затем использовал как
map <foo> (args_for_foo..., items_to_map_over...);
К сожалению, когда я пытаюсь скомпилировать это (используя clang ++),Я получаю следующую ошибку:
map.hpp:14:8: error: class template partial specialization contains template
parameters that cannot be deduced; this partial specialization will never
be used
[-Wunusable-partial-specialization]
struct Map
^~~
map.hpp:8:8: note: non-deducible template parameter 'ReturnType'
class ReturnType,
^
map.hpp:9:8: note: non-deducible template parameter 'Item'
class Item,
^
map.hpp:10:11: note: non-deducible template parameter 'ArgumentTypes'
class... ArgumentTypes,
^
map.hpp:11:7: note: non-deducible template parameter 'f'
auto f,
^
map.hpp:12:11: note: non-deducible template parameter 'Items'
class... Items
^
1 error generated.
Теперь я не удивлюсь, если ему не понравится тот факт, что ArgumentTypes...
дважды появляется в моей специализации, хотя это не говорит об этом напрямую..
Что именно идет не так, и как я могу построить примитив карты таким образом, чтобы этого избежать? Я не хочу хранить копии или ссылки на какие-либо аргументы,потому что это не должно быть необходимым.Если бы я вручную писал шаблон, специализирующий типы функций и параметров, мне не нужно было бы ничего хранить.Это исключает обертки для кортежей в качестве опции.
РЕДАКТИРОВАТЬ: по запросу добавлена информация об использовании.
РЕДАКТИРОВАТЬ: Исправлено чрезмерное использование ссылочных квалификаторов rvalue во избежание путаницы.