Передача функции constexpr для использования во время компиляции

0

Я пытаюсь сделать простой способ генерации std::array во время компиляции. До сих пор это была борьба за то, чтобы найти хороший способ передать функцию constexpr во время компиляции. Обходной путь, который я нашел до сих пор, выглядит следующим образом.

#include <iostream>                                                                
#include <array>                                                                   
namespace a {                                                                      
constexpr int f(const int & i) { return i * i * i;}                                
#include "generate_with_function.hpp"                                              
}                                                                                  
int main()                                                                         
{                                                                                  
    auto arr  = a::generator<false,10,0>::array;                                   
    for (auto i : arr) {                                                           
        std::cout << i << " ";                                                     
    }                                                                              
    return 0;                                                                      
}  

это в основном предполагает, что вы определите функцию, называемую f и я завернул ее в пространство имен, я хотел бы сделать другое. Я хотел знать, есть ли более умный способ передать функцию и использовать ее во время компиляции. Также здесь приведен код, который составляет список.

template <bool B, size_t Count,int ... Nums>                                       
struct generator;                                                                  

template <size_t Count>                                                            
struct generator<false,Count,0>                                                    
{                                                                                  
    constexpr static std::array<int,Count> array                                   
        = generator<false,Count,1,f(0)>::array;                                    
};                                                                                 

template <size_t Count, int Current, int ... Results>                              
struct generator<false,Count,Current, Results...>                                  
{                                                                                  
    constexpr static std::array<int,Count>  array                                  
        = generator<Current+1==Count,Count,Current+1,f(Current), Results...>::array;
};                                                                                 

template <size_t Count, int Current, int ... Results>                              
struct generator<true,Count,Current,Results...>                                    
{                                                                                  
    constexpr static std::array<int,Count>  array{{Results...}};                   
}; 

и прежде чем вы спросите, у меня нет реальной потребности в этом.

Как отмечалось в @us2012, я должен быть конкретным относительно того, что я бы предпочел.

  1. nowrapping в пространстве имен
  2. чтобы написать функцию, но не передавать ее в любом месте
  3. и не требуя, чтобы функция называлась f
Теги:
c++11
constexpr

1 ответ

2
Лучший ответ

Фактически вы можете использовать функцию в качестве параметра шаблона, называемого Gen:

template <bool B, size_t Count, int Current, int Gen(size_t), int ... Nums>
struct generator;

template <size_t Count, int Current, int Gen(size_t), int ... Results>
struct generator<false,Count,Current, Gen, Results...>
{
    constexpr static std::array<int,Count>  array
         generator<Current+1==Count,Count,Current+1,Gen,
                   Gen(Current), Results...>::array;
};

template <size_t Count, int Current, int Gen(size_t), int ... Results>
struct generator<true,Count,Current,Gen,Results...>
{
    constexpr static std::array<int,Count>  array{{Results...}};
};

При этом он фактически выполняет передачу функции constexpr в шаблон (если тип точно соответствует):

// helper to hide the "internal" template parameters
template <size_t Count, int Gen(size_t)>
struct gen {                                                                 
   constexpr static std::array<int, Count> array = generator<false, Count, 0, Gen>::array;
};

constexpr int f(size_t i) { return i * i * i; }

int main()
{
    auto arr = gen<10,f>::array;
    for (auto i : arr) {
        std::cout << i << " ";
    }
    return 0;
}

Вы также можете переключать параметры Gen(Current) и Results... чтобы получить значения в "правильных" индексах массива.

  • 0
    Похоже, это может сработать, хотя функция принимает int
  • 0
    @aaronman: Как написано здесь, это работает, только если функция принимает size_t , но, вероятно, ее можно обобщить, добавив еще один параметр шаблона для типа параметра функции или около того.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню