SFINAE 序列化共享指针失败

SFINAE failure serializing shared pointer

本文关键字:失败 指针 共享 序列化 SFINAE      更新时间:2023-10-16

我正在尝试在 c++14 模式下使用 boost 1.58、gcc 5.4 将 boost 序列化模板专用化为指向具有特定基类的对象的共享指针。 我相信我有正确的 SFINAE 设置来专门化该函数,但编译器不会像我期望的那样选择该函数。

#include <memory>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
class Artifact {
public:
Artifact() {}
virtual ~Artifact() {} // make polymorphic
};
class TestArtifact: public Artifact {
public:
TestArtifact() : Artifact() {}
};

namespace boost {
namespace serialization {
template <class Archive, class T>
void serialize(Archive &ar,
std::shared_ptr<typename std::enable_if<std::is_base_of<Artifact,T>::value,T>::type>& artifact,
//std::shared_ptr<T>& artifact,
unsigned int version) {
// save common Artifact structure on save ...
// Use factory to create specific Artifact (like TestArtifact) shared pointer
// from common Artifact info on load
}
}
}
int main(int argc, char** argv) {
auto t = std::make_shared<TestArtifact>();
std::cout << typeid(std::shared_ptr<TestArtifact>).name() << std::endl;
std::cout << typeid(std::shared_ptr<typename std::enable_if<std::is_base_of<Artifact,TestArtifact>::value,TestArtifact>::type>).name() << std::endl;
std::ofstream ofs(argv[1]);
boost::archive::binary_oarchive ar(ofs);
ar << t;
}

当我构建这段代码时(使用 g++ -std=c++14 -o test_template test_template.cpp -lboost_system -lboost_serialization),我收到以下错误(在正常的"必需自件"列表之后),

/usr/include/boost/serialization/access.hpp:118:9: error: ‘class std::shared_ptr<TestArtifact>’ has no member named ‘serialize’
t.serialize(ar, file_version);

这告诉我我没有正确设置SFINAE。 当我交换注释掉的行以专门用于std::shared_ptr<T>时,代码按预期构建和运行,但我不想踩踏标准的 boost 共享指针序列化专用化。 当我使用过于通用的专业化运行并打印std::shared_ptr<TestArtifact>的类型 ID 和 SFINAE 类输出时,它们是相同的(使用此编译器,我得到的输出为St10shared_ptrI12TestArtifactE两者都如此),所以我不明白为什么我的 SFINAE 序列化函数没有得到识别。

问题是T在这里无法推断。

不要将std::enable_if放在函数参数中,而是将其放在单独的模板参数中。

template <class Archive, class T, typename std::enable_if<std::is_base_of<Artifact,T>::value>::type* = nullptr>
void serialize(Archive &ar, std::shared_ptr<T>& artifact, unsigned int version) { ... }