如何找到 child class 的最大可能大小
How to find the largest possible sizeof child class
给定一个 class,我想在编译时找到最大的 sizeof()
所有子 classes。在这种情况下,您需要正确定义 B::BIGGEST_TYPE_SIZE
的值,最好是在 class 本身中。
可以在单独的代码块中使用 std::max()
来完成此操作,如最后一行所示,但这是一些重复的代码且不优雅,因为我将不得不不断修改它更多 class 继承自 B
.
我想要一个很好的可扩展解决方案。
struct B
{
static const int BIGGEST_TYPE_SIZE;
};
struct D1 : public B
{
int i;
};
struct D2 : public B
{
std::vector<int> vec;
};
struct D3 : public B
{
std::string s;
};
const int B::BIGGEST_TYPE_SIZE = std::max(sizeof(D1), std::max(sizeof(D2), sizeof(D3)));
BIGGEST_TYPE_SIZE
的值应为“32”,因为 std::string
。
对此有什么优雅的解决方案吗?
模板越性感越好。
谢谢!
以std::variant
, it knows its size from the template arguments. Your best shot is also to use a variadic template. First, you implement the variadic max
function template为例,那么你使用它:
template <typename ... Ts>
constexpr bool biggest_size_v = max(sizeof(Ts)...);
如果您要求自动获取 compile-time 处所有派生的 类 的列表。你不能。您仍然需要列出它们:
const int B::BIGGEST_TYPE_SIZE = biggest_size_v<D1, D2, D3>;
It is possible to do so in a separate chunk of code with the usage of std::max as shown in the last line, but it's some what duplicate code and unelegant, as I will have to continuously modify that line as more classes inherit from B.
I would like a nice scalable solution instead.
不幸的是,我不知道自动识别所有派生类型的方法(我不认为这是可能的)所以我担心您需要“随着更多 classes 继承不断修改该行表格 B
".
在 LogicStuff 的回答中,您看到了一种简化该行的优雅方法,我还记得存在接收 std::initializer_list
(constexpr
从 C++14 开始的 std::max()
版本) 所以你也可以写(但是 biggest_size_v
方式更好,恕我直言)
const int B::BIGGEST_TYPE_SIZE
= std::max({sizeof(D1), sizeof(D2), sizeof(D3)});
避免多次 std::max()
调用。
有点跑题了,我想,但我建议你使用 semi-automatic 方法来检查 compile-time,即 B::BIGGEST_TYPE_SIZE
大于(或等于)sizeof()
所有派生类型(至少所有实例化的派生类型)。
如果您修改 B
添加带有 static_assert()
的构造函数(或启用 SFINAE,如果您愿意)
struct B
{
static const int BIGGEST_TYPE_SIZE;
template <std::size_t DerSize>
B (std::integral_constant<std::size_t, DerSize>)
{ static_assert( DerSize <= BIGGEST_TYPE_SIZE, "!" ); }
};
并添加一个继承自 B
的模板 C
结构
template <typename Der>
struct C : public B
{
C() : B{std::integral_constant<std::size_t, sizeof(Der)>{}}
{ }
};
如果您将 Dx
classes 修改为继承 B
通过 C<Dx>
(因此使用 CRTP)
struct D1 : public C<D1>
{ int i; };
struct D2 : public C<D2>
{ std::vector<int> vec; };
struct D3 : public C<D3>
{ std::string s; };
你 auto-magically 在 B
构造函数中启用 compile-time 检查。
因此,如果您添加以下内容,例如 D4
class
struct D4 : public C<D4>
{ int a[42]; };
并且忘记修改 BIGGEST_TYPE_SIZE
初始化,在列表中添加 sizeof(D4)
,声明一个 D4
对象,你得到一个编译错误
D4 d4; // compilation error
下面是一个完整的编译示例
#include <vector>
#include <iostream>
#include <algorithm>
struct B
{
static const int BIGGEST_TYPE_SIZE;
template <std::size_t DerSize>
B (std::integral_constant<std::size_t, DerSize>)
{ static_assert( DerSize <= BIGGEST_TYPE_SIZE, "!" ); }
};
template <typename Der>
struct C : public B
{
C() : B{std::integral_constant<std::size_t, sizeof(Der)>{}}
{ }
};
struct D1 : public C<D1>
{ int i; };
struct D2 : public C<D2>
{ std::vector<int> vec; };
struct D3 : public C<D3>
{ std::string s; };
struct D4 : public C<D4>
{ int a[42]; };
const int B::BIGGEST_TYPE_SIZE
= std::max({sizeof(D1), sizeof(D2), sizeof(D3)}); // <-- sizeof(D4) forgotten !!!
int main ()
{
D1 d1;
D2 d2;
D3 d3;
// D4 d4; compilation error
}
给定一个 class,我想在编译时找到最大的 sizeof()
所有子 classes。在这种情况下,您需要正确定义 B::BIGGEST_TYPE_SIZE
的值,最好是在 class 本身中。
可以在单独的代码块中使用 std::max()
来完成此操作,如最后一行所示,但这是一些重复的代码且不优雅,因为我将不得不不断修改它更多 class 继承自 B
.
我想要一个很好的可扩展解决方案。
struct B
{
static const int BIGGEST_TYPE_SIZE;
};
struct D1 : public B
{
int i;
};
struct D2 : public B
{
std::vector<int> vec;
};
struct D3 : public B
{
std::string s;
};
const int B::BIGGEST_TYPE_SIZE = std::max(sizeof(D1), std::max(sizeof(D2), sizeof(D3)));
BIGGEST_TYPE_SIZE
的值应为“32”,因为 std::string
。
对此有什么优雅的解决方案吗? 模板越性感越好。 谢谢!
以std::variant
, it knows its size from the template arguments. Your best shot is also to use a variadic template. First, you implement the variadic max
function template为例,那么你使用它:
template <typename ... Ts>
constexpr bool biggest_size_v = max(sizeof(Ts)...);
如果您要求自动获取 compile-time 处所有派生的 类 的列表。你不能。您仍然需要列出它们:
const int B::BIGGEST_TYPE_SIZE = biggest_size_v<D1, D2, D3>;
It is possible to do so in a separate chunk of code with the usage of std::max as shown in the last line, but it's some what duplicate code and unelegant, as I will have to continuously modify that line as more classes inherit from B.
I would like a nice scalable solution instead.
不幸的是,我不知道自动识别所有派生类型的方法(我不认为这是可能的)所以我担心您需要“随着更多 classes 继承不断修改该行表格 B
".
在 LogicStuff 的回答中,您看到了一种简化该行的优雅方法,我还记得存在接收 std::initializer_list
(constexpr
从 C++14 开始的 std::max()
版本) 所以你也可以写(但是 biggest_size_v
方式更好,恕我直言)
const int B::BIGGEST_TYPE_SIZE
= std::max({sizeof(D1), sizeof(D2), sizeof(D3)});
避免多次 std::max()
调用。
有点跑题了,我想,但我建议你使用 semi-automatic 方法来检查 compile-time,即 B::BIGGEST_TYPE_SIZE
大于(或等于)sizeof()
所有派生类型(至少所有实例化的派生类型)。
如果您修改 B
添加带有 static_assert()
的构造函数(或启用 SFINAE,如果您愿意)
struct B
{
static const int BIGGEST_TYPE_SIZE;
template <std::size_t DerSize>
B (std::integral_constant<std::size_t, DerSize>)
{ static_assert( DerSize <= BIGGEST_TYPE_SIZE, "!" ); }
};
并添加一个继承自 B
C
结构
template <typename Der>
struct C : public B
{
C() : B{std::integral_constant<std::size_t, sizeof(Der)>{}}
{ }
};
如果您将 Dx
classes 修改为继承 B
通过 C<Dx>
(因此使用 CRTP)
struct D1 : public C<D1>
{ int i; };
struct D2 : public C<D2>
{ std::vector<int> vec; };
struct D3 : public C<D3>
{ std::string s; };
你 auto-magically 在 B
构造函数中启用 compile-time 检查。
因此,如果您添加以下内容,例如 D4
class
struct D4 : public C<D4>
{ int a[42]; };
并且忘记修改 BIGGEST_TYPE_SIZE
初始化,在列表中添加 sizeof(D4)
,声明一个 D4
对象,你得到一个编译错误
D4 d4; // compilation error
下面是一个完整的编译示例
#include <vector>
#include <iostream>
#include <algorithm>
struct B
{
static const int BIGGEST_TYPE_SIZE;
template <std::size_t DerSize>
B (std::integral_constant<std::size_t, DerSize>)
{ static_assert( DerSize <= BIGGEST_TYPE_SIZE, "!" ); }
};
template <typename Der>
struct C : public B
{
C() : B{std::integral_constant<std::size_t, sizeof(Der)>{}}
{ }
};
struct D1 : public C<D1>
{ int i; };
struct D2 : public C<D2>
{ std::vector<int> vec; };
struct D3 : public C<D3>
{ std::string s; };
struct D4 : public C<D4>
{ int a[42]; };
const int B::BIGGEST_TYPE_SIZE
= std::max({sizeof(D1), sizeof(D2), sizeof(D3)}); // <-- sizeof(D4) forgotten !!!
int main ()
{
D1 d1;
D2 d2;
D3 d3;
// D4 d4; compilation error
}