如何设计可序列化类以使任何非序列化属性都会导致编译时错误
How to design a serializable class such that any non-serialized attribute leads to a compile-time error?
说您有以下代码:
class A {
bool _attribute1;
};
// Arbitrarily using std::string, not the point of this question
std::string serialize(const A&);
现在,开发人员将新的bool _attribute2
添加到class A
,而忘记更新serialize
功能,这会在运行时导致错误。(已经去过那里?)
有没有办法将此问题转变为编译时错误?由于C 不支持反射,我感到这是不可能的,但我可能会缺少任何东西。
如果您使用的是C 1Z,则可以使用结构化绑定:
struct S {
bool b;
//bool c; // causes error
};
int main() {
S s;
auto [x] = s;
(void)x;
}
[live demo]
以下一个应与C 11一起工作。
确实有点棘手,它基于@samvarshavchik的评论:
#include<cstddef>
#include<functional>
template<std::size_t> struct Int { int i; };
template<std::size_t> struct Char { char c; };
template<std::size_t> struct Bool { bool c; };
template<typename, template<std::size_t> class...>
struct Base;
template<template<std::size_t> class... T, std::size_t... I>
struct Base<std::index_sequence<I...>, T...>: T<I>... {};
template<template<std::size_t> class... T>
struct Check final: Base<std::make_index_sequence<sizeof...(T)>, T...> {};
class A final {
bool _attribute1;
bool _attribute2;
private:
char _attribute3;
// int _attribute4;
};
void serialize(const A &) {
static_assert(sizeof(A) == sizeof(Check<Bool, Bool, Char>), "!");
// do whatever you want here...
}
int main() {
serialize(A{});
}
基本思想是列出数据成员的所有类型,并使用混合蛋白从中定义新类型。然后是将static_assert
放在正确的位置的问题。
请注意,私人数据成员也被考虑。
存在某些角色可能会破坏它,但也许它可以适用于您的真实代码。
作为旁注,如果是C 14,则可以进一步简化:
#include<cstddef>
template<typename... T>
constexpr std::size_t size() {
std::size_t s = 0;
std::size_t _[] = { s += sizeof(T)... };
(void)_;
return s;
}
class A final {
bool _attribute1;
bool _attribute2;
private:
char _attribute3;
// int _attribute4;
};
void serialize(const A &) {
static_assert(sizeof(A) == size<bool, bool, char>(), "!");
// ...
}
int main() {
serialize(A{});
}
如果您注定要使用C 11,并且您仍然有兴趣仅使用列表初始化使用给定参数构建类型类型,但甚至没有任何类型的类型:
#include <type_traits>
struct default_param {
template <class T>
operator T();
};
template <class T, class...>
using typer = T;
template <class, class, class... Args>
struct cannot_one_more: std::true_type {};
template <class Tested, class... Args>
struct cannot_one_more<typer<void, decltype(Tested{std::declval<Args>()..., default_param{}})>, Tested, Args...>: std::false_type {
};
template <class...>
struct is_list_constructable: std::false_type {};
template <class Tested, class... Args>
struct is_list_constructable<Tested(Args...)>: is_list_constructable<void, Tested, Args...> { };
template <class Tested, class... Args>
struct is_list_constructable<typer<void, decltype(Tested{std::declval<Args>()...}), typename std::enable_if<cannot_one_more<void, Tested, Args...>::value>::type>, Tested, Args...>: std::true_type { };
struct S {
bool b;
//bool c; // causes error
};
int main() {
static_assert(is_list_constructable<S(bool)>::value, "!");
}
[live demo]
相关文章:
- 如何在C++中序列化结构数据
- 序列化,没有库的整数,得到奇怪的结果
- 如何知道QDataStream不能反序列化某些内容
- 如何使用Python从C++中读取谷物序列化数据
- 如何使用boost::具有嵌套结构和最小代码更改的序列化
- 带有Protobuf序列化的C++Hazelcast:字符串不是UTF-8格式的
- 自定义对象的dlib序列化在gcc中失败
- C++boost序列化多态性问题
- 增强基于 XML class_id的反序列化
- 提升反序列化对象具有 nan 或 -nan 值
- 在 cpp 中的平面缓冲区中序列化对象
- 每次进行继承时都需要提升::序列化::base_object吗?
- 如何在 c++ 非托管代码中反序列化 byte[] 的 json 字符串?
- 提升序列化 1:73 的向后兼容性问题
- 设置使用 Cereal 序列化库时可以在序列化函数中访问的属性
- 如何设计可序列化类以使任何非序列化属性都会导致编译时错误
- boost::serialization-序列化从泛型属性/功能容器派生的类
- 如何使用boost::序列化将对象的矢量作为属性序列化对象
- boost属性树值(反)序列化
- QML 对象属性的部分序列化