我正在制作一个框架,它将读取Tiled的XML文件,并且生成的对象(tpp :: File)将是纯不可变的(不包含setters或复制构造函数/赋值运算符)。基本上,它使用builder pattern的想法,但不是有2个具有相同属性的对象,而是用主属性和另一个用来“包装”它的属性。不可变类和复制构造函数
// Represents a Tiled's TMX file. This object is immutable.
class TILEDPP_API File final
{
public:
File() = default;
File(tpp::File&&) = default;
File(const tpp::File&) = delete;
File(const tpp::Path& path, tpp::FileMetadata& metadata);
File& operator = (tpp::File&&) = default;
File& operator = (const tpp::File&) = delete;
const tpp::Path& getPath() const;
const tpp::Header& getHeader() const;
const tpp::Layers& getLayers() const;
const tpp::TileSets& getTileSets() const;
private:
const tpp::Path m_path;
tpp::FileMetadata m_metadata; // Should be const!
};
// Represents the content of a Tiled's TMX file (header, sets, layers etc).
// This struct is non-copyable due to its HUGE size.
struct TILEDPP_API FileMetadata final
{
FileMetadata() = default;
FileMetadata(tpp::FileMetadata&&) = default;
FileMetadata(const tpp::FileMetadata&) = delete;
FileMetadata& operator = (FileMetadata&&) = default;
FileMetadata& operator = (const FileMetadata&) = delete;
tpp::Header header;
tpp::Layers layers;
tpp::TileSets sets;
};
然后,在某个文件创建过程中,我们也会有这样:
tpp::File FileReader::read(const std::string& path)
{
tpp::FileMetadata metadata = m_parser.parseMetadata(path);
return tpp::File(path, metadata);
}
上面的代码将使用File(const tpp::Path& path, tpp::FileMetadata& metadata)
构造,符合市场预期。 但是,如果我们使tpp :: File的tpp :: FileMetadata为const,它会尝试使用File(const tpp::File&)
的构造函数,而不是删除。它为什么会发生?!
作为参考,该项目可以找到here。任何想法也非常感谢。
嗨,@Yakk!感谢您的回复!您能否请赐教我:'FileMetaData不支持从FileMetadata中移出const &&)。所以你在File(File &&)中的默认值不起作用;没有默认的实现可以工作。另外,如何为移动从“添加支持”需要删除移动构造函数/分配操作符? –
@YvesHenri你在哪里看到“添加支持”?你在引用谁?您的设计无法支持移动;你想要不变性,你不能有移动支持。关于移动支持的最初评论是我推断你*想*移动支持;我只是说你不能拥有它。 '=默认'实际上没有实现它们;所以我明确表示它是'= delete'd。然后,我改变了return语句来构造就地而不是移入返回值。这有严重的局限性,正如我在最后一行之前所描述的那样。在最后一行之后,我说“好吧,这是另一种解决方案”。 – Yakk