想象一个更大的项目,包含一些参数结构:
struct pars {
int foo;
};
以这个结构体作为参数,实现其他功能,例如:
// (de)serialization into different formats
static pars FromString(string const &text);
static string ToString(pars const &data);
static pars FromFile(string const &filename);
// [...]
// comparison / calculation / verification
static bool equals(pars l, pars r);
static pars average(pars a, pars b);
static bool isValid(pars p);
// [...]
// you-name-it
现在假设需要向该结构添加一个新成员:
struct pars {
int foo;
int bar; // new member
};
是否有一种设计模式可以中断构建或发出警告,直到调整所有必要的代码位置?
示例:
- 如果我将
int foo
更改为string foo
,我将不会错过任何需要更改的代码行。 - 如果
int foo
需要更改为unsigned int foo
,我可以将foo
重命名为foo_u
并且让编译器指出需要调整的地方。
一个部分解决方案是使成员私有(private)
并且只能从构造函数中设置,必须使用所有参数调用:
pars::pars(int _foo, int _bar)
: foo(_foo), bar(_bar)
{ }
这确保了 pars 的正确创建,但不是使用 - 所以这会在 FromString()
中捕获缺失的改编,但在ToString()
.
单元测试只会在测试期间(我正在搜索编译时方法)和(反)序列化部分揭示此类问题,而不是正在考虑新的 bar
无处不在(在比较/计算/验证/...功能中也是如此)。
最佳答案
将流操作与流的源或目标分离。
一个非常简单的例子:
#include <sstream>
#include <fstream>
struct pars
{
int foo;
int bar;
static constexpr auto current_version = 2;
};
std::istream &deserialise(std::istream &is, pars &model)
{
int version;
is >> version;
is >> model.foo;
if (version > 1) {
is >> model.bar;
}
return is;
}
std::ostream &serialise(std::ostream &os, const pars &model)
{
os << model.current_version << " ";
os << model.foo << " ";
// a version 2 addition
os << model.bar<< " ";
return os;
}
static pars FromString(std::string const &text)
{
std::istringstream iss(text);
auto result = pars();
deserialise(iss, result);
return result;
}
static std::string ToString(pars const &data)
{
std::ostringstream oss;
serialise(oss, data);
return oss.str();
}
static pars FromFile(std::string const &filename)
{
auto file = std::ifstream(filename);
auto result = pars();
deserialise(file, result);
return result;
}
另请参阅:
boost.serialization http://www.boost.org/doc/libs/1_64_0/libs/serialization/doc/index.html
Cereal https://github.com/USCiLab/cereal
等等
关于c++ - 是否存在针对新成员的编译器强制执行完整性的模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46363526/