2017-02-16 2 views
-1

Tiled의 XML 파일을 읽을 프레임 워크를 만들고 결과 객체 (tpp :: File)는 순수 변경 불가능 (설정자 또는 복사 생성자/할당 연산자 없음)됩니다. 기본적으로 종류는 builder pattern 아이디어를 사용하지만 동일한 속성을 가진 두 개의 객체가있는 대신 주 속성과 객체를 "포장"합니다.변경 불가능한 클래스 및 복사 생성자

// 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; 
}; 

그런 다음, 어딘가에 파일 생성 과정에서, 우리는이있을 것이다 : 예상대로 위의 코드 조각의 File(const tpp::Path& path, tpp::FileMetadata& metadata) 생성자를 사용합니다

tpp::File FileReader::read(const std::string& path) 
{ 
    tpp::FileMetadata metadata = m_parser.parseMetadata(path); 

    return tpp::File(path, metadata); 
} 

. 그러나 우리가 tpp :: File의 tpp :: FileMetadata const를 만들면 이 대신 File(const tpp::File&) 생성자를 사용하려고 시도합니다. 왜 그런 일이 일어날까요?!

프로젝트를 참조하려면 here을 참조하십시오. 어떤 생각도 매우 높이 평가됩니다. 그것은 File(const tpp::File&) 생성자를 사용하려고합니다

답변

0

대신

대신 잘못된 단어입니다.

마찬가지로 올바른 단어입니다.

C++ 17 이전에는 임시로 File을 생성하고 함수에서 이동 생성 된 복사본을 반환합니다. (이 이동 구조는 생략 될 수 있으며, C++ 17에서는 더 이상 이동 된 복사본이 없습니다).

FileMetaData은 (는) FileMetadata const&&)에서 이동을 지원하지 않습니다. 따라서 =default (File(File&&))이 작동하지 않습니다. 기본 구현이 작동하지 않습니다.


개체는 변경 불가능하고 실제로 이동할 수 없습니다.

변경할 수없는 개체는 실제로 C++에서 이동할 수 없습니다. 파괴 중에는 불변이지만, 이동 전에는 이 파괴되기 전에이 불변 일 필요가 있습니다. 그래서 당신은 "그들의 상태를 찢어"다른 곳으로 옮길 수 없습니다. 당신이 이동-에서, File불변하지 수 원하는 경우

File(tpp::File&&) = default; 
File& operator = (tpp::File&&) = default; 

: 가 이동-에서을 지원하기 위해을하려는 당신이 나타납니다 때문에

나는,이 상태. 변경할 수 없으면 File을 옮길 수 없습니다.

그래서, 당신은 불변성을 유지하고 싶다고 가정 해보십시오.


return tpp::File(path, metadata) 

return {std::move(path), std::move(metadata)}; 

을 변경, 그 =delete 확인 및 변경

File(const tpp::Path& path, tpp::FileMetadata& metadata); 

File(tpp::Path&& path, tpp::FileMetadata&& metadata); 

귀하의 코드가 컴파일됩니다.

read을 호출하려면 또는 auto&&에 반환 값을 저장하십시오. 즉, read 반품 반환 값을 참조하십시오.

반환 된 File은 변경할 수없는 개체가 허용하지 않는 File에서 이동해야하므로 수명이 긴 변수에 저장할 수 없습니다.


또는 불변의 상태로 되돌릴 수 있습니다.을 제외하고는 을 불변으로 만듭니다.

을 제외한 의 불변 인 객체는 이동시 데이터가 변경되므로 데이터를 const으로 저장하지 않습니다. 그들에 대한 다른 모든 방법은 const입니다.

+0

안녕하세요, @Yakk! 답장을 보내 주셔서 감사합니다! 이걸 제게 알려주십시오.'FileMetaData는 FileMetadata const &&에서의 이동을 지원하지 않습니다. 따라서 File (File &&)의 your = default는 작동하지 않습니다; 기본 구현이 효과가 없다 .' 또한 move-from에 대한 "추가 지원"은 move constructor/assigment 연산자를 * 삭제할 필요가 있습니까? –

+0

@YvesHenri "지원 추가"는 어디에서 볼 수 있습니까? 누구를 인용하고 있습니까? 디자인에서 이동 시작을 지원할 수 없습니다. 당신은 불변성을 원한다. 당신은 움직일 수 없다. 이동 지원에 대한 초기 의견은 당신을 추론하여 * 지원을 원합니다. 나는 그저 네가 가질 수 없다고 진술한다. '= default'는 실제로 그것들을 구현하지 않았습니다; 그래서 나는 그것이'= delete'd라는 것을 명시했다. 그런 다음 return 문을 반환 값으로 이동하는 대신 내부에서 생성하도록 변경했습니다. 마지막 줄 앞에 설명 할 때 심각한 제한이 있습니다. 마지막 라인이 끝나면, "글쎄, 여기 또 다른 해결책이있다."라고 말합니다. – Yakk