Is too late to play?
Given a list X1-X8 of features, I propose to add a template class that maps number from 0 to 7 to classes X1-X8 and inherit from X1-X8 only if a first boolean template parameter is true
template <bool, std::size_t>
struct Feature
{ };
template <> struct Feature<true, 0> : public X1 { };
template <> struct Feature<true, 1> : public X2 { };
template <> struct Feature<true, 2> : public X3 { };
template <> struct Feature<true, 3> : public X4 { };
template <> struct Feature<true, 4> : public X5 { };
template <> struct Feature<true, 5> : public X6 { };
template <> struct Feature<true, 6> : public X7 { };
template <> struct Feature<true, 7> : public X8 { };
Now a Feature_helper struct, that inherit the right Feature for every bit in a std::uint8_t number, is simple
template <std::uint8_t, typename = std::make_index_sequence<8u>>
struct Feature_helper;
template <std::uint8_t u8, std::size_t ... Is>
struct Feature_helper<u8, std::index_sequence<Is...>>
: public Feature<(u8 & (1 << Is)) != 0u, Is>...
{ };
and A become
template <std::uint8_t u8>
class A : public Feature_helper<u8>
{ };
The following is a full compiling example
#include <cstdint>
#include <utility>
#include <type_traits>
struct X1 { };
struct X2 { };
struct X3 { };
struct X4 { };
struct X5 { };
struct X6 { };
struct X7 { };
struct X8 { };
template <bool, std::size_t>
struct Feature
{ };
template <> struct Feature<true, 0> : public X1 { };
template <> struct Feature<true, 1> : public X2 { };
template <> struct Feature<true, 2> : public X3 { };
template <> struct Feature<true, 3> : public X4 { };
template <> struct Feature<true, 4> : public X5 { };
template <> struct Feature<true, 5> : public X6 { };
template <> struct Feature<true, 6> : public X7 { };
template <> struct Feature<true, 7> : public X8 { };
template <std::uint8_t, typename = std::make_index_sequence<8u>>
struct Feature_helper;
template <std::uint8_t u8, std::size_t ... Is>
struct Feature_helper<u8, std::index_sequence<Is...>>
: public Feature<(u8 & (1 << Is)) != 0u, Is>...
{ };
template <std::uint8_t u8>
class A : public Feature_helper<u8>
{ };
int main()
{
static_assert( true == std::is_base_of_v<X1, A<5u>> );
static_assert( false == std::is_base_of_v<X2, A<5u>> );
static_assert( true == std::is_base_of_v<X3, A<5u>> );
static_assert( false == std::is_base_of_v<X4, A<5u>> );
static_assert( false == std::is_base_of_v<X5, A<5u>> );
static_assert( false == std::is_base_of_v<X6, A<5u>> );
static_assert( false == std::is_base_of_v<X7, A<5u>> );
static_assert( false == std::is_base_of_v<X8, A<5u>> );
}
-- EDIT --
The OP observe
Found a downside, class inheriting Feature_helper would not be a direct derived class of a Feature. Meaning it cannot inherit constructors from X1, X2, ...
Not sure to understand your requirement but I suppose you can solve the problem (if there isn't collision between Feature construnctors) using a lot of using.
I've added, in the following example, a int contructor for X1 and a long constructor for X2.
Observe the X1() = default; and X2() = default;: adding an explicit constructor the default constructors/destructors are deleted; so you have to re-default them explicitly (maybe also copy/move constructors).
#include <cstdint>
#include <utility>
#include <iostream>
#include <type_traits>
struct X1 { X1(int) { std::cout << "X1 constructor" << std::endl; }
X1() = default; };
struct X2 { X2(long) { std::cout << "X2 constructor" << std::endl; }
X2() = default; };
struct X3 { };
struct X4 { };
struct X5 { };
struct X6 { };
struct X7 { };
struct X8 { };
template <bool, std::size_t>
struct Feature
{ };
template <> struct Feature<true, 0> : public X1 { using X1::X1; };
template <> struct Feature<true, 1> : public X2 { using X2::X2; };
template <> struct Feature<true, 2> : public X3 { };
template <> struct Feature<true, 3> : public X4 { };
template <> struct Feature<true, 4> : public X5 { };
template <> struct Feature<true, 5> : public X6 { };
template <> struct Feature<true, 6> : public X7 { };
template <> struct Feature<true, 7> : public X8 { };
template <std::uint8_t, typename = std::make_index_sequence<8u>>
struct Feature_helper;
template <std::uint8_t u8, std::size_t ... Is>
struct Feature_helper<u8, std::index_sequence<Is...>>
: public Feature<(u8 & (1 << Is)) != 0u, Is>...
{ using Feature<(u8 & (1 << Is)) != 0u, Is>::Feature...; };
template <std::uint8_t u8>
class A : public Feature_helper<u8>
{ using Feature_helper<u8>::Feature_helper; };
int main()
{
static_assert( true == std::is_base_of_v<X1, A<5u>> );
static_assert( false == std::is_base_of_v<X2, A<5u>> );
static_assert( true == std::is_base_of_v<X3, A<5u>> );
static_assert( false == std::is_base_of_v<X4, A<5u>> );
static_assert( false == std::is_base_of_v<X5, A<5u>> );
static_assert( false == std::is_base_of_v<X6, A<5u>> );
static_assert( false == std::is_base_of_v<X7, A<5u>> );
static_assert( false == std::is_base_of_v<X8, A<5u>> );
A<3u> a1(1); // call the X1(int) constructor
A<3u> a2(2l); // call the X2(long) constructor
}