Рекурсивно предложив Jarod42, я предлагаю рекурсивную структуру MakeMyMap
с static
func()
, которая получает последовательность аргументов std::pair<T1, T2>
[наблюдение: 42 - верхняя граница по умолчаниюдля количества std::pair
аргументов].
template <typename T1, typename T2, std::size_t Dim>
struct MyMap
{
std::array<std::pair<T1, T2>, Dim> map;
};
template <typename T, std::size_t>
using getTheType = T;
template <typename, typename, typename = std::make_index_sequence<42u>>
struct MakeMyMap;
template <typename T1, typename T2, std::size_t ... Is>
struct MakeMyMap<T1, T2, std::index_sequence<Is...>>
: public MakeMyMap<T1, T2, std::make_index_sequence<sizeof...(Is)-1u>>
{
using MakeMyMap<T1, T2, std::make_index_sequence<sizeof...(Is)-1u>>::func;
static auto func (getTheType<std::pair<T1, T2>, Is> const & ... ps)
{ return MyMap<T1, T2, sizeof...(Is)>{ { { ps... } } }; }
};
template <typename T1, typename T2>
struct MakeMyMap<T1, T2, std::index_sequence<>>
{
static auto func ()
{ return MyMap<T1, T2, 0u>{ }; }
};
Таким образом, вы можете написать
auto map = MakeMyMap<int, std::string>::func(
{ 42, "the answer to the ultimate questions" },
{ 23, "some other stuff" }
);
Ниже приведена полная компиляция (достаточно C ++ 14), пример
#include <array>
#include <string>
#include <utility>
template <typename T1, typename T2, std::size_t Dim>
struct MyMap
{
std::array<std::pair<T1, T2>, Dim> map;
};
template <typename T, std::size_t>
using getTheType = T;
template <typename, typename, typename = std::make_index_sequence<42u>>
struct MakeMyMap;
template <typename T1, typename T2, std::size_t ... Is>
struct MakeMyMap<T1, T2, std::index_sequence<Is...>>
: public MakeMyMap<T1, T2, std::make_index_sequence<sizeof...(Is)-1u>>
{
using MakeMyMap<T1, T2, std::make_index_sequence<sizeof...(Is)-1u>>::func;
static auto func (getTheType<std::pair<T1, T2>, Is> const & ... ps)
{ return MyMap<T1, T2, sizeof...(Is)>{ { { ps... } } }; }
};
template <typename T1, typename T2>
struct MakeMyMap<T1, T2, std::index_sequence<>>
{
static auto func ()
{ return MyMap<T1, T2, 0u>{ }; }
};
int main ()
{
auto map = MakeMyMap<int, std::string>::func(
{ 42, "the answer to the ultimate questions" },
{ 23, "some other stuff" }
);
static_assert( std::is_same<decltype(map),
MyMap<int, std::string, 2u>>::value, "!" );
}
Используя C ++ 17, вы можете использовать std::string_view
вместо std::string
, вы можете определить constexpr
функции func()
, поэтому map
может быть constexpr
constexpr auto map = MakeMyMap<int, std::string_view>::func(
{ 42, "the answer to the ultimate questions" },
{ 23, "some other stuff" }
);
и вы также можете проверить, что
static_assert( std::is_same<decltype(map),
MyMap<int, std::string_view, 2u> const>::value, "!" );
Используя новый C ++ 17 variadic using
, вы можете избежать рекурсии при всех переключениях MakeMyMap
следующим образом
template <typename, typename, typename = std::make_index_sequence<42u>>
struct MakeMyMap;
template <typename T1, typename T2, std::size_t ... Is>
struct MakeMyMap<T1, T2, std::index_sequence<Is...>>
: public MMM_helper<T1, T2, std::make_index_sequence<Is>>...
{ using MMM_helper<T1, T2, std::make_index_sequence<Is>>::func...; };
где MMM_helper
(помощник Make My Map) определяется следующим образом
template <typename, typename, typename>
struct MMM_helper;
template <typename T1, typename T2, std::size_t ... Is>
struct MMM_helper<T1, T2, std::index_sequence<Is...>>
{
static constexpr auto func (getTheType<std::pair<T1, T2>, Is> const & ... ps)
{ return MyMap<T1, T2, sizeof...(Is)>{ { { ps... } } }; }
};
Ниже приводится полный C ++ 17, не рекурсивный, пример
#include <array>
#include <string_view>
#include <utility>
template <typename T1, typename T2, std::size_t Dim>
struct MyMap
{
std::array<std::pair<T1, T2>, Dim> map;
};
template <typename T, std::size_t>
using getTheType = T;
template <typename, typename, typename>
struct MMM_helper;
template <typename T1, typename T2, std::size_t ... Is>
struct MMM_helper<T1, T2, std::index_sequence<Is...>>
{
static constexpr auto func (getTheType<std::pair<T1, T2>, Is> const & ... ps)
{ return MyMap<T1, T2, sizeof...(Is)>{ { { ps... } } }; }
};
template <typename, typename, typename = std::make_index_sequence<42u>>
struct MakeMyMap;
template <typename T1, typename T2, std::size_t ... Is>
struct MakeMyMap<T1, T2, std::index_sequence<Is...>>
: public MMM_helper<T1, T2, std::make_index_sequence<Is>>...
{ using MMM_helper<T1, T2, std::make_index_sequence<Is>>::func...; };
int main ()
{
constexpr auto map = MakeMyMap<int, std::string_view>::func(
{ 42, "the answer to the ultimate questions" },
{ 23, "some other stuff" }
);
static_assert( std::is_same<decltype(map),
MyMap<int, std::string_view, 2u> const>::value, "!" );
}