我正在尝试使用奇怪的重复模板模式在hdf5组中存储内容。 但我有两个问题:
(代码如下)hdf5::Group
表示hdf5组,可以存储数据集。hdf5::Storable
是CRTP模板类。函数hdf5::store
应该采用一个组和一个可存储的对象,并调用该对象的实现。所有这些都应该在命名空间hdf5
内,以保持清洁。
A
实现了一个可存储的。它位于hdf5
命名空间之外(例如全局或其他命名空间)。实施方法A::store
应该是私有的,以确保每个人都使用hdf5::store
。
有问题的部分有评论指出问题。
#include <string>
#include <iostream>
namespace hdf5 {
/// A group can contain other groups, and datasets.
class Group {
public:
/// Create a group under a parent group.
Group(Group* parent, const std::string &name)
: parent_(parent), name_(name)
{
std::cout << "Creating group \"" << name << "\"";
if (parent != nullptr)
std::cout << " under \"" << parent->name_ << "\"";
std::cout << "." << std::endl;
};
/// Create a root group.
Group() : Group(nullptr, "root") { }
/// Create a dataset inside.
void create_dataset(const std::string &name)
{
std::cout << "Creating dataset \"" << name << "\""
<< " under \"" << name_ << "\"." << std::endl;
}
private:
Group *parent_;
std::string name_;
};
/** Abstraction of a storable class.
*
* Curiously recurring template pattern.
* Makes it possible to write
*
* store(grp, obj);
*
*/
template<class Derived>
class Storable {
friend void hdf5::store(hdf5::Group &grp, const Derived &obj) {
obj.store(grp);
}
};
} // namespace hdft
/// Some data class that should be storable.
class A : private hdf5::Storable<A> {
public:
A(const std::string &name) : name_(name) { }
/*
* Why can't I make it private? `store` should be friend.
*
* test.cc: In instantiation of ‘void hdf5::store(hdf5::Group&, const A&)’:
* test.cc:104:19: required from here
* test.cc:72:10: error: ‘void A::store(hdf5::Group&) const’ is private
* void store(hdf5::Group &grp) const {
* ^
* test.cc:45:9: error: within this context
* obj.store(grp);
* ^
*/
// private:
public:
/// Implementation of the storage
void store(hdf5::Group &grp) const {
grp.create_dataset(name_);
}
private:
std::string name_;
};
/// Demonstration.
int main(void) {
hdf5::Group root,
grpa(&root, std::string("group_a")),
grpb(&root, std::string("group_b"));
A a1(std::string("A1")), a2(std::string("A2"));
/*
* This is what I want, but it doesn't compile:
*
* test.cc: In function ‘int main()’:
* test.cc:96:5: error: ‘store’ is not a member of ‘hdf5’
* hdf5::store(root, a1);
* ^
*/
// hdf5::store(root, a1);
// hdf5::store(root, a2);
// hdf5::store(grpa, a1);
// hdf5::store(grpb, a2);
/*
* This OTOH compiles and runs.
*/
store(root, a1);
store(root, a2);
store(grpa, a1);
store(grpb, a2);
}
Creating group "root".
Creating group "group_a" under "root".
Creating group "group_b" under "root".
Creating dataset "A1" under "root".
Creating dataset "A2" under "root".
Creating dataset "A1" under "group_a".
Creating dataset "A2" under "group_b".
答案 0 :(得分:1)
以下更改似乎有效:https://ideone.com/CRuLkb
namespace hdf5 {
// Previous stuff
template <class Derived> void store(hdf5::Group &grp, const Derived&obj);
template<class Derived>
class Storable {
static void store(hdf5::Group &grp, const Derived&obj)
{
obj.store(grp);
}
friend void hdf5::store<>(hdf5::Group &grp, const Derived&obj);
};
template <class Derived>
void store(hdf5::Group &grp, const Derived&obj) {
Storable<Derived>::store(grp, obj);
}
} // namespace hdf5
/// Some data class that should be storable.
class A : private hdf5::Storable<A> {
friend class hdf5::Storable<A>;
private:
/// Implementation of the storage
void store(hdf5::Group &grp) const {
grp.create_dataset(name_);
}
private:
std::string name_;
};