4

Есть ли способ сделать constexpr -Array целых без знака, которые выполняют некоторый предикат, заданный логической функцией constexpr pred(std::size_t)?Заполнение массива на compiletime под некоторым предикатом

Я пробовал много, особенно с помощью indices trick, чтобы узнать, что мои данные слишком велики, так что они превышают предел рекурсивного шаблона 256. Я не смогу изменить этот предел, если его можно изменить.

Как спросили в комментариях, вот некоторые псевдо-код, что я хотел бы достичь:

template<std::size_t... Is> 
struct Sequence{}; 

template<std::size_t N, std::size_t... Is> 
struct SequenceGenerator : SequenceGenerator<N-1, N-1, Is...> 
{}; //obviously here it gets too deep into recursion, as mentioned 

template<std::size_t... Is> 
struct SequenceGenerator<0, Is...> : Sequence<Is...> 
{}; 

template<std::size_t N> 
struct MyData 
{ 
    std::size_t values[N]; 

    static constexpr std::size_t size() 
    { return N; } 
}; 

template<typename Lambda, std::size_t... Is> 
constexpr MyData<sizeof...(Is)> MyGen(Sequence<Is...>, Lambda func) 
{ 
    if(func(Is)...) 
     return {{ Is... }}; 
    else 
     return /*some not-invalidating but current element discarding thing*/ 
} 

template<std::size_t N, typename Lambda> 
constexpr Generator<N> MyGen(Lambda func) 
{ 
    return MyGen(SequenceGenerator<N>(), func); 
} 

constexpr bool pred(std::size_t i) noexcept 
{ 
    //some condition making up a "range" 
    return i < 360ULL && i > 2ULL; 
} 
+1

Можете ли вы показать нам (псевдо) код того, чего бы вы хотели достичь? Может быть, с небольшим набором данных, который не превышает предела, но в противном случае работает и показывает нам, что вы имеете в виду? –

+0

@ DanielFrey Добавлен код – NaCl

+0

Так ваша идея «фильтровать» диапазон по заданному предикату? Кроме того, если вы ищете эффективный «генератор последовательности», я написал библиотеку, содержащую [с логарифмической глубиной создания] (https://github.com/Arcoth/VTMPL/blob/master/index_list.hxx). – Columbo

ответ

5

Единственное решение, которое я мог придумать, чтобы использовать генератор для последовательности, которая является одновременно

  • O (N журнал)
  • фильтр при генерации последовательности

Сказанное, я начал with this O(log N) generator, и я сменил предикат с функции constexpr на более удобный std::integral_constant - я надеюсь, что это приемлемо для вас. Результат таков:

#include <utility> 
#include <iostream> 
#include <type_traits> 

template<std::size_t...> struct seq{ using type = seq; }; 

template<class S1, class S2> struct concat; 

template<std::size_t... I1, std::size_t... I2> 
struct concat<seq<I1...>, seq<I2...>> 
    : seq<I1..., I2...>{}; 

template<template<std::size_t> class pred, std::size_t B, std::size_t N> 
struct gen_seq : concat<typename gen_seq<pred, B, N/2>::type, typename gen_seq<pred, B + N/2, N - N/2>::type>::type {}; 

template<template<std::size_t> class pred, std::size_t B> struct gen_seq<pred, B, 0> : seq<> {}; 
template<template<std::size_t> class pred, std::size_t B> struct gen_seq<pred, B, 1> : std::conditional<pred<B>::value,seq<B>,seq<>>::type {}; 

template<std::size_t N> 
struct MyData 
{ 
    std::size_t values[N]; 

    static constexpr std::size_t size() 
    { return N; } 
}; 

template<std::size_t... Is> 
constexpr MyData<sizeof...(Is)> MyGen(seq<Is...>) 
{ 
    return {{ Is... }}; 
} 

template<template<std::size_t> class pred, std::size_t N> 
constexpr auto MyGen() -> decltype(MyGen(typename gen_seq<pred,0,N>::type())) 
{ 
    return MyGen(gen_seq<pred,0,N>()); 
} 

template< std::size_t N > struct my_pred : std::integral_constant< bool, N % 3 == 0 > {}; 

int main() 
{ 
    auto data = MyGen<my_pred, 10>(); 
    static_assert(data.size() == 4, "Oops"); 

    for (auto i : data.values) 
     std::cout << i << std::endl; 

    auto data2 = MyGen<my_pred, 10000>(); 
    static_assert(data2.size() == 3334, "Oops"); 
} 

Live example

Как вы можете видеть в живом примере, даже 10000 работает :)

А версию с constexpr bool pred(std::size_t) не очень удобно (вы не можете просто «вызовите» метод, вам нужно написать еще несколько кода для каждого pred), но это также было возможно.

Смежные вопросы