我已经在github上问了这个问题(大约一个月前),没有任何答案,所以我现在在这里问。
我在项目中使用Cereal作为序列化库。我尝试添加序列化功能std::string_view(基本上是从std::string实现中复制和粘贴)。但是,Cereal会引发编译器错误:
谷物找不到提供的类型和档案组合的任何输出序列化功能。
这是我的实现(我在这里禁用了反序列化,但是我也尝试了一个伪函数,它给了我相同的结果):
#pragma once
#include "../cereal.hpp"
#include <string_view>
namespace cereal
{
//! Serialization for basic_string_view types, if binary data is supported
template <class Archive, class CharT, class Traits>
typename std::enable_if<traits::is_output_serializable<BinaryData<CharT>, Archive>::value, void>::type
CEREAL_SAVE_FUNCTION_NAME(Archive& ar, std::basic_string_view<CharT, Traits> const& str)
{
// Save number of chars + the data
ar(make_size_tag(static_cast<size_type>(str.size())));
ar(binary_data(str.data(), str.size() * sizeof(CharT)));
}
//! Deserialization into std::basic_string_view is forbidden due to its properties as a view.
//! However std::basic_string_view can be deserialized into a std::basic_string.
// template <class Archive, class CharT, class Traits>
// void CEREAL_LOAD_FUNCTION_NAME(Archive& ar, std::basic_string_view<CharT, Traits> & str);
}
Run Code Online (Sandbox Code Playgroud)
最小示例:
#include <iostream>
#include <cereal/string_view>
int main()
{
/*
* Working archive types are:
* - BinaryOutputArchive
* - PortableBinaryOutputArchive
*
* Compiler errors for:
* - JSONOutputArchive
* - XMLOutputArchive
*/
using OutputArchive = cereal::JSONOutputArchive;
std::string_view str = "Hello World!";
{
OutputArchive oar(std::cout);
oar(str);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该测试可以成功编译并通过二进制归档,但不能通过XML和JSON序列化。
我认为这与enable_if条件中的特征有关is_output_serializable<BinaryData<CharT>, Archive>,但是该特征也存在于std::string实现中并且工作得很好。我也找不到的第二个定义或专业化std::string。
为什么我会在XML和JSON档案中遇到该编译器错误?
由于std::string内置了对 JSON 和 XML 序列化器的支持,因此无法在标头中找到它cereal/types/string.hpp。
您必须手动添加对字符串数据的支持,就像对二进制数据所做的那样。
我在谷物图书馆方面没有经验,但在文档中有档案专业化的示例std::map<std::string, std::string>:http://uscilab.github.io/cereal/archive_specialization.html
它使用了稍微不同的 SFINAE 技术和谷物特定性状(is_text_archive请查看同一篇文章的底部)。
鉴于此,对于您的代码,它给出:
namespace cereal
{
template <class Archive, class CharT, class Traits,
traits::EnableIf<traits::is_text_archive<Archive>::value> = traits::sfinae> inline
void save( Archive & ar, std::basic_string_view<CharT, Traits> const & str )
{
/// ...
}
}
Run Code Online (Sandbox Code Playgroud)
注意:文档用于cereal::traits::DisableIf<cereal::traits::is_text_archive<Archive>::value>指定二进制输出专门化。使用它来代替会更加一致is_output_serializable<BinaryData<CharT>,...>