Вот как это сделать. Учитывая ваш шаблон класса some_other_type
:
template<int I, int J>
struct some_other_type { };
И дал некоторые механизмы скрыты в detail
имен:
namespace detail
{
template<int... Is>
struct pairs { };
template<int I, int J>
struct pairs<I, J>
{
using type = std::tuple<some_other_type<I, J>>;
};
template<int I, int J, int... Is>
struct pairs<I, J, Is...>
{
using type = decltype(std::tuple_cat(
std::tuple<some_other_type<I, J>>(),
typename pairs<J, Is...>::type()));
};
}
Вы могли бы обеспечить простую функцию, которая создает экземпляр шаблона вспомогательный класс:
template<int... Is>
typename detail::pairs<Is...>::type pairs()
{
return typename detail::pairs<Is...>::type();
}
И вот как вы его использовали (и тестовый пример):
#include <type_traits>
int main()
{
auto p = pairs<1, 2, 3, 4>();
// Won't fire!
static_assert(
std::is_same<
decltype(p),
std::tuple<
some_other_type<1,2>,
some_other_type<2,3>,
some_other_type<3,4>>
>::value,
"Error!");
}
И, наконец, вот live example.
УЛУЧШЕНИЯ: (почему написание <1, 2, 3, 4>
, когда можно было бы написать <1, 5>
)?
Также возможно расширить вышеупомянутое решение, чтобы не требовалось вручную записывать каждое число между минимумом и максимумом в качестве аргумента шаблона pairs()
. Учитывая дополнительное оборудование ниже, снова спрятался в detail
имен:
namespace detail
{
template <int... Is>
struct index_list { };
template <int MIN, int N, int... Is>
struct range_builder;
template <int MIN, int... Is>
struct range_builder<MIN, MIN, Is...>
{
typedef index_list<Is...> type;
};
template <int MIN, int N, int... Is>
struct range_builder : public range_builder<MIN, N - 1, N - 1, Is...>
{ };
// Meta-function that returns a [MIN, MAX) index range
template<int MIN, int MAX>
using index_range = typename range_builder<MIN, MAX>::type;
template<int... Is>
auto pairs_range(index_list<Is...>) -> decltype(::pairs<Is...>())
{
return ::pairs<Is...>();
}
}
можно определить вспомогательную функцию pairs_range()
, которая принимает 2 аргумента шаблона, определяющие диапазон [begin, end)
- где end
не входит, в стиле Стандартная библиотека:
template<int I, int J>
auto pairs_range() -> decltype(pairs_range(detail::index_range<I, J>()))
{
return pairs_range(detail::index_range<I, J>());
}
И это, как можно было бы использовать его (в том числе теста):
int main()
{
// Won't fire!
static_assert(
std::is_same<
decltype(pairs_range<1, 5>()),
decltype(pairs<1, 2, 3, 4>())
>::value,
"Error!");
}
И еще раз, вот live example.
+1 Это, вероятно, достижима с помощью класса ... –