I want to convert an "array" of bool
to a integer sequence.
So I need to compute an std::array
at compile time.
Here is my code
#include <array>
template<typename InputIt, typename T >
inline constexpr typename std::iterator_traits<InputIt>::difference_type
count( InputIt first, InputIt last, const T &value ) {
typename std::iterator_traits<InputIt>::difference_type ret = 0;
for (; first != last; ++first) {
if (*first == value) {
ret++;
}
}
return ret;
}
template<bool ..._values>
struct keep_value {
static constexpr std::size_t numberOfValues = sizeof...(_values);
static constexpr bool values[] = {_values...};
static constexpr std::size_t numberToKeep = count(values, values + numberOfValues, true);
static constexpr std::array<std::size_t, numberToKeep> computeIndices() {
std::array<std::size_t, numberToKeep> array{};
auto it = array.begin();
for(std::size_t i{0}; i < numberOfValues; ++i)
if(values[i] == true)
*it++ = i;
return array;
}
static constexpr std::array<std::size_t, numberToKeep> indices = computeIndices();
template<typename Indices = std::make_index_sequence<numberToKeep>>
struct as_index_sequence{};
template<std::size_t ...Is>
struct as_index_sequence<std::index_sequence<Is...>> : std::index_sequence<indices[Is]...>{};
};
int main() {
keep_value<false, true, true>::template as_index_sequence<>{}; // Should return the sequence 1 2
}
I get an error for the line that call the computeIndices
function. Is this code c++14 correct? Is it possible to do otherwise?
I am using MSVC and I get this error :
expression did not evaluate to a constant
About correctness answered JVApen (+1).
A possible alternative is avoid
std::array
at all and construct the index sequence in a recursive way using template specializationThe following is a full compilable example
If you don't like the recursive solutions, I propose (just for fun) another solution based of
std::tuple_cat
This code looks correct and works when compiled as C++17. It uses
std::array::begin
, which only has been madeconstexpr
in C++17.A better compilation error can be achieved when using clang, which states: