根据派生的 class 字段指定基础 class 模板参数
Specify base class template parameter depending on the derived class fields
我希望能够根据派生 class 中数据成员的数量,将基 class 中数据成员的类型设置得尽可能小。因此,如果派生 class 中的数据成员数为 5,则基 class 中的数据成员类型应为 std::uint8_t
.
这是我已经尝试过的方法:
#include <iostream>
template <std::size_t N>
struct min {
using type = typename std::conditional_t<
(N <= 8), std::uint8_t,
typename std::conditional_t<
(N <= 16), std::uint16_t,
typename std::conditional_t<
(N <= 32), std::uint32_t, std::uint64_t
>
>
>;
};
template <std::size_t N>
using min_t = typename min<N>::type;
template <typename CrtpT, typename T = min_t<CrtpT::end__ - CrtpT::begin__ + 1>>
struct Wrapper {
T a;
};
struct Foo : Wrapper<Foo> {
static constexpr int begin__ = __LINE__;
static constexpr int F_A = 0;
static constexpr int F_B = 0;
static constexpr int F_C = 0;
static constexpr int end__ = __LINE__;
};
int main() {
Foo foo;
std::cout << static_cast<unsigned>(foo.a) << std::endl;
return 0;
}
这显然不起作用并且无法编译,因为 Foo
class 在 Wrapper
class 定义时未完全指定。
有没有人对如何做到这一点有更好的想法,或者是否有可能?
提前致谢!
当您需要 CRTP 中的完整类型时,解决方法是不使用 CRTP :),而是使用另一种方式进行常规继承:
template <typename T, typename U = min_t<T::end__ - T::begin__ + 1>>
struct Wrapper : T {
U a;
};
struct FooImpl {
static constexpr int begin__ = __LINE__;
static constexpr int F_A = 0;
static constexpr int F_B = 0;
static constexpr int F_C = 0;
static constexpr int end__ = __LINE__;
};
using Foo = Wrapper<FooImpl>;
您可以将静态变量放在一个单独的 Bar
中,让 Foo
继承它和 Wrapper
。
#include <iostream>
template <std::size_t N>
struct min {
using type = typename std::conditional_t<
(N <= 8), std::uint8_t,
typename std::conditional_t<
(N <= 16), std::uint16_t,
typename std::conditional_t<
(N <= 32), std::uint32_t, std::uint64_t
>
>
>;
};
template <std::size_t N>
using min_t = typename min<N>::type;
template <typename CrtpT, typename T = min_t<CrtpT::end__ - CrtpT::begin__ + 1>>
struct Wrapper {
T a = 0;
};
struct Bar {
static constexpr int begin__ = __LINE__;
static constexpr int F_A = 0;
static constexpr int F_B = 0;
static constexpr int F_C = 0;
static constexpr int end__ = __LINE__;
};
struct Foo : Bar, Wrapper<Bar> {};
int main() {
Foo foo;
std::cout << static_cast<unsigned>(foo.a) << std::endl;
return 0;
}
编辑
要使 F_A
、F_B
等成为所选类型,您可以将其设为模板并使用 int
实例化以获取类型。
template <typename T>
struct Bar {
static constexpr int begin__ = __LINE__;
static constexpr T F_A = 0;
static constexpr T F_B = 0;
static constexpr T F_C = 0;
static constexpr int end__ = __LINE__;
};
struct Foo : Bar<Wrapper<Bar<int>>::type>, Wrapper<Bar<int>> {};
我希望能够根据派生 class 中数据成员的数量,将基 class 中数据成员的类型设置得尽可能小。因此,如果派生 class 中的数据成员数为 5,则基 class 中的数据成员类型应为 std::uint8_t
.
这是我已经尝试过的方法:
#include <iostream>
template <std::size_t N>
struct min {
using type = typename std::conditional_t<
(N <= 8), std::uint8_t,
typename std::conditional_t<
(N <= 16), std::uint16_t,
typename std::conditional_t<
(N <= 32), std::uint32_t, std::uint64_t
>
>
>;
};
template <std::size_t N>
using min_t = typename min<N>::type;
template <typename CrtpT, typename T = min_t<CrtpT::end__ - CrtpT::begin__ + 1>>
struct Wrapper {
T a;
};
struct Foo : Wrapper<Foo> {
static constexpr int begin__ = __LINE__;
static constexpr int F_A = 0;
static constexpr int F_B = 0;
static constexpr int F_C = 0;
static constexpr int end__ = __LINE__;
};
int main() {
Foo foo;
std::cout << static_cast<unsigned>(foo.a) << std::endl;
return 0;
}
这显然不起作用并且无法编译,因为 Foo
class 在 Wrapper
class 定义时未完全指定。
有没有人对如何做到这一点有更好的想法,或者是否有可能?
提前致谢!
当您需要 CRTP 中的完整类型时,解决方法是不使用 CRTP :),而是使用另一种方式进行常规继承:
template <typename T, typename U = min_t<T::end__ - T::begin__ + 1>>
struct Wrapper : T {
U a;
};
struct FooImpl {
static constexpr int begin__ = __LINE__;
static constexpr int F_A = 0;
static constexpr int F_B = 0;
static constexpr int F_C = 0;
static constexpr int end__ = __LINE__;
};
using Foo = Wrapper<FooImpl>;
您可以将静态变量放在一个单独的 Bar
中,让 Foo
继承它和 Wrapper
。
#include <iostream>
template <std::size_t N>
struct min {
using type = typename std::conditional_t<
(N <= 8), std::uint8_t,
typename std::conditional_t<
(N <= 16), std::uint16_t,
typename std::conditional_t<
(N <= 32), std::uint32_t, std::uint64_t
>
>
>;
};
template <std::size_t N>
using min_t = typename min<N>::type;
template <typename CrtpT, typename T = min_t<CrtpT::end__ - CrtpT::begin__ + 1>>
struct Wrapper {
T a = 0;
};
struct Bar {
static constexpr int begin__ = __LINE__;
static constexpr int F_A = 0;
static constexpr int F_B = 0;
static constexpr int F_C = 0;
static constexpr int end__ = __LINE__;
};
struct Foo : Bar, Wrapper<Bar> {};
int main() {
Foo foo;
std::cout << static_cast<unsigned>(foo.a) << std::endl;
return 0;
}
编辑
要使 F_A
、F_B
等成为所选类型,您可以将其设为模板并使用 int
实例化以获取类型。
template <typename T>
struct Bar {
static constexpr int begin__ = __LINE__;
static constexpr T F_A = 0;
static constexpr T F_B = 0;
static constexpr T F_C = 0;
static constexpr int end__ = __LINE__;
};
struct Foo : Bar<Wrapper<Bar<int>>::type>, Wrapper<Bar<int>> {};