使用模板检查结构中的字段,如果失败则启用函数,如果失败则给出漂亮的错误消息? 我有一个C++类,它定义了一个数据序列化接口到JSON: class JsonSerializable { public: QJsonDocument toJSON() const; void fromJSON(QJsonDocument const& json); protected: virtual QJsonDocument serialize() const = 0; virtual oid deserialize(QJsonDocument const& json) = 0; };
使用模板检查结构中的字段,如果失败则启用函数,如果失败则给出漂亮的错误消息? 我有一个C++类,它定义了一个数据序列化接口到JSON: class JsonSerializable { public: QJsonDocument toJSON() const; void fromJSON(QJsonDocument const& json); protected: virtual QJsonDocument serialize() const = 0; virtual oid deserialize(QJsonDocument const& json) = 0; };,c++,templates,metaprogramming,C++,Templates,Metaprogramming,toJSON()与serialize()及其对应方法的思想是,类需要实现的受保护方法只需要关心实际处理数据,而公共方法执行基本的有效性检查 现在我想介绍用于更细粒度检查的JSON模式。我只想在存在模式的情况下启用JSON模式部分。因此,我开始引入一个struct,如下所示: template <class Serializable> struct JsonSchema {}; template <> struct JsonSchema<MySerializ
toJSON()
与serialize()
及其对应方法的思想是,类需要实现的受保护方法只需要关心实际处理数据,而公共方法执行基本的有效性检查
现在我想介绍用于更细粒度检查的JSON模式。我只想在存在模式的情况下启用JSON模式部分。因此,我开始引入一个struct
,如下所示:
template <class Serializable>
struct JsonSchema {};
template <>
struct JsonSchema<MySerializingClass>
{
static const char schemaURI[] = "...";
};
模板
结构JsonSchema{};
模板
结构JsonSchema
{
静态常量char schemaURI[]=“…”;
};
我尚未完成该方法,因为我不确定如何实现以下目标:
JsonSchema
结构的模板专门化时,才应编译fromJSON()
中的模式检查代码schemaURI
字段是否存在,以及它的大小是否大于0。如果没有,我想给程序员一个描述性的错误消息,就像我可以使用BOOST\u STATIC\u ASSERT
一样可能吗?API尚未最终确定;这里最重要的部分是检查应该在编译时进行。
schemaURI
参数由程序员设置,在运行时不会更改---模式文件是分布式程序的一部分,通过资源系统进行管理,因此如果程序编译,它保证可用。我相信您当前的设计不可能满足您的要求。例如,您的fromJSON
示例代码不可能静态地知道调用它的类的类型。由于您需要编译类型检查,我认为您可能必须使用静态多态性,如下所示:
template<typename T>
struct JsonSchema {};
template<typename Derived, typename SchemaCheck = void>
class JsonSerializable {
public:
QJsonDocument toJSON() const;
void fromJSON(QJsonDocument const& json);
};
template<typename Derived, typename SchemaCheck>
QJsonDocument JsonSerializable<Derived,SchemaCheck>::toJSON() const {
// do whatever you need to do here, and call serialize() like this:
static_cast<Derived const*>(this)->serialize();
}
template<typename Derived, typename SchemaCheck>
void JsonSerializable<Derived,SchemaCheck>::fromJSON(QJsonDocument const& json) {
// do whatever you need to do when there's no schema, and call deserialize() like this:
static_cast<Derived*>(this)->deserialize(json);
}
template<typename Derived>
class JsonSerializable<Derived,
// We check extent > 1 instead of extent > 0 because a string constant of length 0 requires an array of length 1 to hold it.
// If schemaURI doesn't exist at all, this will also fail and cause the default version (above) to be used.
std::enable_if<(std::extent<decltype(JsonSchema<Derived>::schemaURI)>::value > 1), Derived>> {
public:
// It's probably easier to define these inline. It might get pretty complicated otherwise.
QJsonDocument toJSON() const {
// Pretty much the same as before, unless you need some different behaviour when there's a schema
static_cast<Derived const*>(this)->serialize();
}
void fromJSON(QJsonDocument const& json) {
// There's a schema now, so act accordingly.
static_cast<Derived*>(this)->deserialize(json);
}
};
class MySerializingClass : public JsonSerializable<MySerializingClass> {
public:
QJsonDocument serialize() const;
void deserialize(QJsonDocument const& json);
};
template<typename Derived>
class JsonSerializable<Derived,
// We check extent > 1 instead of extent > 0 because a string constant of length 0 requires an array of length 1 to hold it.
std::enable_if<(std::extent<decltype(JsonSchema<Derived>::schemaURI)>::value > 1), Derived>> : public JsonSerializableBase
然后将JsonSerializable
声明更改为从中继承:
template<typename Derived, typename SchemaCheck = void>
class JsonSerializable : public JsonSerializableBase
希望它能满足您的需要。如果有人想知道,如果静态多态性不是一个选项,例如,当Qt的moc干扰时,如何实现这一点:那么,一个自由函数可以帮助您。代码如下:
class JsonSerializable
{
public:
virtual QJsonDocument toJSON() const = 0;
virtual void fromJSON(const QJsonDocument &json) = 0;
};
template <class C>
struct JsonSchema
{
static constexpr char const schemaURI[] = "";
};
template <
class C,
typename std::enable_if<(std::is_base_of<JsonSerializable, C>
::value
&& std::extent<decltype(JsonSchema<C>::schemaURI)>
::value <= 1),
int>::type = 0>
void deserialize(C& serializable, QJsonDocument const& json)
{
serializable.fromJSON(json);
}
template <
class C,
typename std::enable_if<(std::is_base_of<JsonSerializable, C>
::value
&& std::extent<decltype(JsonSchema<C>::schemaURI)>
::value > 1),
int>::type = 0>
void deserialize(C& serializable, QJsonDocument const& json)
{
/* Do the schema checking here: */
checkSchema(json, JsonSerializable<C>::schemaURI);
serializable.fromJSON(json);
}
类JsonSerializable
{
公众:
虚拟QJsonDocument toJSON()常量=0;
来自json的虚拟void(const QJsonDocument&json)=0;
};
模板
结构JsonSchema
{
静态constexpr char const schemaURI[]=“”;
};
模板<
丙级,,
typename std::启用\u如果
void反序列化(C&serializable,qjsondocumentconst&json)
{
serializable.fromJSON(json);
}
模板<
丙级,,
typename std::启用_(如果为1),
int>::type=0>
void反序列化(C&serializable,qjsondocumentconst&json)
{
/*在此处执行架构检查:*/
checkSchema(json,JsonSerializable::schemaURI);
serializable.fromJSON(json);
}
其中一部分可能不可能(检查大小是否大于0)。如果您需要
const-char[]
而不是const-char*
,const-char[]
可能会更合理,请原谅这个错误。一切都应该在编译时发生,所以static const char[]
可能更好。。。我会调整我的问题。谢谢我不认为这是一个错误-constchar*
毕竟是分配字符串文字时使用的正常方法,而且它没有错。使用const char[]
意味着编译器应该知道它的长度-我相信在
中可能有一些东西可以获得数组类型的长度。顺便说一下,您可以这样声明:static const char schemaURI[]=“…”代码>谢谢!长度检查是一个很好的选择,我打赌如果其余的工作正常,我会得到。。。关于模板魔术有什么想法吗?是的,这确实告诉了我怎么做。因为我的API还没有完成,所以我可以很容易地实现它。非常感谢!
using QJsonDocument = std::string; // Since I don't have Qt handy
int main(int,char*[]) {
MySerializingClass foo;
foo.toJSON();
foo.fromJSON("abc");
return 0;
}
class JsonSerializable
{
public:
virtual QJsonDocument toJSON() const = 0;
virtual void fromJSON(const QJsonDocument &json) = 0;
};
template <class C>
struct JsonSchema
{
static constexpr char const schemaURI[] = "";
};
template <
class C,
typename std::enable_if<(std::is_base_of<JsonSerializable, C>
::value
&& std::extent<decltype(JsonSchema<C>::schemaURI)>
::value <= 1),
int>::type = 0>
void deserialize(C& serializable, QJsonDocument const& json)
{
serializable.fromJSON(json);
}
template <
class C,
typename std::enable_if<(std::is_base_of<JsonSerializable, C>
::value
&& std::extent<decltype(JsonSchema<C>::schemaURI)>
::value > 1),
int>::type = 0>
void deserialize(C& serializable, QJsonDocument const& json)
{
/* Do the schema checking here: */
checkSchema(json, JsonSerializable<C>::schemaURI);
serializable.fromJSON(json);
}