Reputation: 21
My problem is that I want to get the index of the element of an integer_sequence. The very naive version is below. I would like to have a meta-function taking using a variadic template on the enum type and taking as input the integer_sequence and the Type for which the index is required. Something similar exists in monster.hpp. I would better avoiding importing the whole package (it is not the smallest one) only for a function.
#include <iostream>
#include <utility>
using namespace std;
namespace animalsExperiment{
///////////////////////////////////////////////////////////////////////////////
enum class Animals {
CAT = 15,
DOG = 19,
RABBIT = 43
};
///////////////////////////////////////////////////////////////////////////////
constexpr auto AllAnimals = integer_sequence<
Animals,
Animals::CAT,
Animals::DOG,
Animals::RABBIT
>{};
template<Animals P>
constexpr int animalIndex = 0;
///////////////////////////////////////////////////////////////////////////////
template<>
constexpr int animalIndex<Animals::DOG> = 1;
///////////////////////////////////////////////////////////////////////////////
template<>
constexpr int animalIndex<Animals::RABBIT> = 2;
}
Upvotes: 0
Views: 469
Reputation: 21
Using the nice Inputs I could come out with a potential solution
#include <utility>
#include <array>
using namespace std;
namespace enumExperiment{
///////////////////////////////////////////////////////////////////////////////
template<typename E>
auto AllValues = integer_sequence<
E>{};
///////////////////////////////////////////////////////////////////////////////
template<typename E, E Probe, auto... Values>
constexpr int valueIndexImpl(integer_sequence<E, Values...>) {
std::array myValues{Values...};
for (size_t i = 0; i < myValues.size(); i++)
if (myValues[i] == Probe)
return i;
return -1;
}
///////////////////////////////////////////////////////////////////////////////
template<typename E, E Probe>
constexpr int valueIndex() {
return valueIndexImpl<E,Probe>(AllValues<E>);
};
///////////////////////////////////////////////////////////////////////////////
enum class Animals {
CAT = 15,
DOG = 19,
RABBIT = 43
};
///////////////////////////////////////////////////////////////////////////////
template<>
auto AllValues<Animals> = integer_sequence<
Animals,
Animals::CAT,
Animals::DOG,
Animals::RABBIT
>{};
///////////////////////////////////////////////////////////////////////////////
enum class Vegetables {
EGGPLANT = 18,
CARROT = 26,
LETTUCE = 37
};
///////////////////////////////////////////////////////////////////////////////
template<>
auto AllValues<Vegetables> = integer_sequence<
Vegetables,
Vegetables::EGGPLANT,
Vegetables::CARROT,
Vegetables::LETTUCE
>{};
static_assert(valueIndex<Animals, Animals::DOG>() == 1);
static_assert(valueIndex<Animals, Animals::RABBIT>() == 2);
static_assert(valueIndex<Animals, Animals::CAT>() == 0);
static_assert(valueIndex<Vegetables, Vegetables::CARROT>() == 1);
}
Still I am asking myself which is the metaprogramming syntax to get the enum class out of the enum class value. When I give Vegetables::CARROT the compiler must know that the enum class is Vegetables compile tyme reflection should be possible. Would be great to get a metafunction enumStructure on the value returning the value and the type (eunumStructure::value, eunumStructure::type). The Problem is that it would be based on a non-type template, but the type of the template should be in the result. Still this would make the external interface even simpler.
Upvotes: 0
Reputation: 42776
With some helper function
constexpr auto AllAnimals = integer_sequence<
Animals,
Animals::CAT,
Animals::DOG,
Animals::RABBIT
>{};
template<Animals P, auto... Values>
constexpr int animalIndexImpl(integer_sequence<Animals, Values...>) {
std::array animals{Values...};
for (size_t i = 0; i < animals.size(); i++)
if (animals[i] == P)
return i;
return 0;
}
template<Animals P>
constexpr int animalIndex() {
return animalIndexImpl<P>(AllAnimals);
};
static_assert(animalIndex<Animals::DOG>() == 1);
static_assert(animalIndex<Animals::RABBIT>() == 2);
Upvotes: 2