来不及玩了?
给定 X1-X8 的功能列表,我建议添加一个模板类,将数字从 0 映射到类 X1-X8 并仅继承自 X1-X8如果第一个布尔模板参数是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 { };
现在是一个 Feature_helper 结构,它为 std::uint8_t 数字中的每一位继承正确的 Feature,很简单
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>...
{ };
和A 变成
template <std::uint8_t u8>
class A : public Feature_helper<u8>
{ };
以下是完整的编译示例
#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>> );
}
-- 编辑--
OP 观察
发现一个缺点,继承Feature_helper 的类不会是Feature 的直接派生类。这意味着它不能从X1、X2、...继承构造函数。
不确定是否理解您的要求,但我想您可以使用大量 using 来解决问题(如果 Feature 构造函数之间没有冲突)。
在下面的示例中,我为X1 添加了一个int 构造函数,为X2 添加了一个long 构造函数。
观察X1() = default; 和X2() = default;:添加显式构造函数会删除默认构造函数/析构函数;所以你必须明确地重新默认它们(也许还有复制/移动构造函数)。
#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
}