#include <iostream>
class our_string {
public:
void reserve(std::size_t size) {}
std::size_t size() const { return 0; }
void append(const our_string& other) { }
};
std::ostream& operator<<(std::ostream& lhs, const our_string& rhs) {
return lhs;
}
template<typename Derived> class ConcatenationExpressionBase {
public:
std::size_t size() const {
return static_cast<Derived>(this)->size();
}
void add_to_string(our_string& result) const {
return static_cast<Derived>(this)->add_to_string(result);
}
};
class ConcatenateString : public ConcatenationExpressionBase<ConcatenateString> {
public:
ConcatenateString(const our_string* str)
: p(str) {}
ConcatenateString(const ConcatenateString& other)
: p(other.p) {}
const our_string* p;
std::size_t size() const {
return p->size();
}
void add_to_string(our_string& result) const {
result.append(*p);
}
};
template<typename LHS, typename RHS> class ConcatResult : public ConcatenationExpressionBase<ConcatResult<LHS, RHS>> {
public:
ConcatResult(LHS l, RHS r)
: lhs(l), rhs(r) {}
ConcatResult(const ConcatResult& other)
: lhs(other.lhs), rhs(other.rhs) {}
LHS lhs;
RHS rhs;
std::size_t size() const {
return lhs.size() + rhs.size();
}
void add_to_string(our_string& result) const {
lhs.add_to_string(result);
rhs.add_to_string(result);
}
};
ConcatResult<ConcatenateString, ConcatenateString> operator+(const our_string& lhs, const our_string& rhs) {
return ConcatResult<ConcatenateString, ConcatenateString>(&lhs, &rhs);
}
template<typename LHS> ConcatResult<LHS, ConcatenateString> operator+(const ConcatenationExpressionBase<LHS>& lhs, const our_string& rhs) {
return ConcatResult<LHS, ConcatenateString>(static_cast<const LHS&>(lhs), &rhs);
}
template<typename RHS> ConcatResult<ConcatenateString, RHS> operator+(const our_string& lhs, const ConcatenationExpressionBase<RHS>& rhs) {
return ConcatResult<ConcatenateString, RHS>(&lhs, static_cast<const RHS&>(rhs));
}
template<typename LHS, typename RHS> ConcatResult<LHS, RHS> operator+(const ConcatenationExpressionBase<LHS>& lhs, const ConcatenationExpressionBase<RHS>& rhs) {
return ConcatResult<LHS, RHS>(static_cast<const LHS&>(lhs), static_cast<const RHS&>(rhs));
}
template<typename T> std::ostream& operator<<(std::ostream& lhs, const ConcatenationExpressionBase<T>& rhs) {
our_string result;
result.reserve(rhs.size());
rhs.add_to_string(result);
return lhs << result;
}
int main() {
std::cout << our_string() + our_string() + our_string();
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKY2xhc3Mgb3VyX3N0cmluZyB7CnB1YmxpYzoKICAgdm9pZCByZXNlcnZlKHN0ZDo6c2l6ZV90IHNpemUpIHt9CiAgIHN0ZDo6c2l6ZV90IHNpemUoKSBjb25zdCB7IHJldHVybiAwOyB9CiAgIHZvaWQgYXBwZW5kKGNvbnN0IG91cl9zdHJpbmcmIG90aGVyKSB7IH0KfTsKCnN0ZDo6b3N0cmVhbSYgb3BlcmF0b3I8PChzdGQ6Om9zdHJlYW0mIGxocywgY29uc3Qgb3VyX3N0cmluZyYgcmhzKSB7CiAgIHJldHVybiBsaHM7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIERlcml2ZWQ+IGNsYXNzIENvbmNhdGVuYXRpb25FeHByZXNzaW9uQmFzZSB7CnB1YmxpYzoKICAgIHN0ZDo6c2l6ZV90IHNpemUoKSBjb25zdCB7CiAgICAgICAgcmV0dXJuIHN0YXRpY19jYXN0PERlcml2ZWQ+KHRoaXMpLT5zaXplKCk7CiAgICB9CiAgICB2b2lkIGFkZF90b19zdHJpbmcob3VyX3N0cmluZyYgcmVzdWx0KSBjb25zdCB7CiAgICAgICAgcmV0dXJuIHN0YXRpY19jYXN0PERlcml2ZWQ+KHRoaXMpLT5hZGRfdG9fc3RyaW5nKHJlc3VsdCk7CiAgICB9Cn07CmNsYXNzIENvbmNhdGVuYXRlU3RyaW5nIDogcHVibGljIENvbmNhdGVuYXRpb25FeHByZXNzaW9uQmFzZTxDb25jYXRlbmF0ZVN0cmluZz4gewpwdWJsaWM6CiAgICBDb25jYXRlbmF0ZVN0cmluZyhjb25zdCBvdXJfc3RyaW5nKiBzdHIpCiAgICAgICAgOiBwKHN0cikge30KICAgIENvbmNhdGVuYXRlU3RyaW5nKGNvbnN0IENvbmNhdGVuYXRlU3RyaW5nJiBvdGhlcikKICAgICAgICA6IHAob3RoZXIucCkge30KICAgIGNvbnN0IG91cl9zdHJpbmcqIHA7CiAgICBzdGQ6OnNpemVfdCBzaXplKCkgY29uc3QgewogICAgICAgIHJldHVybiBwLT5zaXplKCk7CiAgICB9CiAgICB2b2lkIGFkZF90b19zdHJpbmcob3VyX3N0cmluZyYgcmVzdWx0KSBjb25zdCB7CiAgICAgICAgcmVzdWx0LmFwcGVuZCgqcCk7CiAgICB9Cn07CnRlbXBsYXRlPHR5cGVuYW1lIExIUywgdHlwZW5hbWUgUkhTPiBjbGFzcyBDb25jYXRSZXN1bHQgOiBwdWJsaWMgQ29uY2F0ZW5hdGlvbkV4cHJlc3Npb25CYXNlPENvbmNhdFJlc3VsdDxMSFMsIFJIUz4+IHsKcHVibGljOgogICAgQ29uY2F0UmVzdWx0KExIUyBsLCBSSFMgcikKICAgICAgICA6IGxocyhsKSwgcmhzKHIpIHt9CiAgICBDb25jYXRSZXN1bHQoY29uc3QgQ29uY2F0UmVzdWx0JiBvdGhlcikKICAgICAgICA6IGxocyhvdGhlci5saHMpLCByaHMob3RoZXIucmhzKSB7fQogICAgTEhTIGxoczsKICAgIFJIUyByaHM7CiAgICBzdGQ6OnNpemVfdCBzaXplKCkgY29uc3QgewogICAgICAgIHJldHVybiBsaHMuc2l6ZSgpICsgcmhzLnNpemUoKTsKICAgIH0KICAgIHZvaWQgYWRkX3RvX3N0cmluZyhvdXJfc3RyaW5nJiByZXN1bHQpIGNvbnN0IHsKICAgICAgICBsaHMuYWRkX3RvX3N0cmluZyhyZXN1bHQpOwogICAgICAgIHJocy5hZGRfdG9fc3RyaW5nKHJlc3VsdCk7CiAgICB9Cn07CkNvbmNhdFJlc3VsdDxDb25jYXRlbmF0ZVN0cmluZywgQ29uY2F0ZW5hdGVTdHJpbmc+IG9wZXJhdG9yKyhjb25zdCBvdXJfc3RyaW5nJiBsaHMsIGNvbnN0IG91cl9zdHJpbmcmIHJocykgewogICAgcmV0dXJuIENvbmNhdFJlc3VsdDxDb25jYXRlbmF0ZVN0cmluZywgQ29uY2F0ZW5hdGVTdHJpbmc+KCZsaHMsICZyaHMpOwp9CnRlbXBsYXRlPHR5cGVuYW1lIExIUz4gQ29uY2F0UmVzdWx0PExIUywgQ29uY2F0ZW5hdGVTdHJpbmc+IG9wZXJhdG9yKyhjb25zdCBDb25jYXRlbmF0aW9uRXhwcmVzc2lvbkJhc2U8TEhTPiYgbGhzLCBjb25zdCBvdXJfc3RyaW5nJiByaHMpIHsKICAgIHJldHVybiBDb25jYXRSZXN1bHQ8TEhTLCBDb25jYXRlbmF0ZVN0cmluZz4oc3RhdGljX2Nhc3Q8Y29uc3QgTEhTJj4obGhzKSwgJnJocyk7Cn0KdGVtcGxhdGU8dHlwZW5hbWUgUkhTPiBDb25jYXRSZXN1bHQ8Q29uY2F0ZW5hdGVTdHJpbmcsIFJIUz4gb3BlcmF0b3IrKGNvbnN0IG91cl9zdHJpbmcmIGxocywgY29uc3QgQ29uY2F0ZW5hdGlvbkV4cHJlc3Npb25CYXNlPFJIUz4mIHJocykgewogICAgcmV0dXJuIENvbmNhdFJlc3VsdDxDb25jYXRlbmF0ZVN0cmluZywgUkhTPigmbGhzLCBzdGF0aWNfY2FzdDxjb25zdCBSSFMmPihyaHMpKTsKfQp0ZW1wbGF0ZTx0eXBlbmFtZSBMSFMsIHR5cGVuYW1lIFJIUz4gQ29uY2F0UmVzdWx0PExIUywgUkhTPiBvcGVyYXRvcisoY29uc3QgQ29uY2F0ZW5hdGlvbkV4cHJlc3Npb25CYXNlPExIUz4mIGxocywgY29uc3QgQ29uY2F0ZW5hdGlvbkV4cHJlc3Npb25CYXNlPFJIUz4mIHJocykgewogICAgcmV0dXJuIENvbmNhdFJlc3VsdDxMSFMsIFJIUz4oc3RhdGljX2Nhc3Q8Y29uc3QgTEhTJj4obGhzKSwgc3RhdGljX2Nhc3Q8Y29uc3QgUkhTJj4ocmhzKSk7Cn0KdGVtcGxhdGU8dHlwZW5hbWUgVD4gc3RkOjpvc3RyZWFtJiBvcGVyYXRvcjw8KHN0ZDo6b3N0cmVhbSYgbGhzLCBjb25zdCBDb25jYXRlbmF0aW9uRXhwcmVzc2lvbkJhc2U8VD4mIHJocykgewogICAgb3VyX3N0cmluZyByZXN1bHQ7CiAgICByZXN1bHQucmVzZXJ2ZShyaHMuc2l6ZSgpKTsKICAgIHJocy5hZGRfdG9fc3RyaW5nKHJlc3VsdCk7CiAgICByZXR1cm4gbGhzIDw8IHJlc3VsdDsKfQppbnQgbWFpbigpIHsKICAgc3RkOjpjb3V0IDw8IG91cl9zdHJpbmcoKSArIG91cl9zdHJpbmcoKSArIG91cl9zdHJpbmcoKTsKfQ==
prog.cpp: In member function 'size_t ConcatenationExpressionBase<Derived>::size() const [with Derived = ConcatResult<ConcatResult<ConcatenateString, ConcatenateString>, ConcatenateString>, size_t = unsigned int]':
prog.cpp:67:5: instantiated from 'std::ostream& operator<<(std::ostream&, const ConcatenationExpressionBase<LHS>&) [with T = ConcatResult<ConcatResult<ConcatenateString, ConcatenateString>, ConcatenateString>, std::ostream = std::basic_ostream<char>]'
prog.cpp:72:58: instantiated from here
prog.cpp:17:49: error: no matching function for call to 'ConcatResult<ConcatResult<ConcatenateString, ConcatenateString>, ConcatenateString>::ConcatResult(const ConcatenationExpressionBase<ConcatResult<ConcatResult<ConcatenateString, ConcatenateString>, ConcatenateString> >* const)'
prog.cpp:41:5: note: candidates are: ConcatResult<LHS, RHS>::ConcatResult(const ConcatResult<LHS, RHS>&) [with LHS = ConcatResult<ConcatenateString, ConcatenateString>, RHS = ConcatenateString, ConcatResult<LHS, RHS> = ConcatResult<ConcatResult<ConcatenateString, ConcatenateString>, ConcatenateString>]
prog.cpp:39:5: note: ConcatResult<LHS, RHS>::ConcatResult(LHS, RHS) [with LHS = ConcatResult<ConcatenateString, ConcatenateString>, RHS = ConcatenateString]
prog.cpp: In member function 'void ConcatenationExpressionBase<Derived>::add_to_string(our_string&) const [with Derived = ConcatResult<ConcatResult<ConcatenateString, ConcatenateString>, ConcatenateString>]':
prog.cpp:68:5: instantiated from 'std::ostream& operator<<(std::ostream&, const ConcatenationExpressionBase<LHS>&) [with T = ConcatResult<ConcatResult<ConcatenateString, ConcatenateString>, ConcatenateString>, std::ostream = std::basic_ostream<char>]'
prog.cpp:72:58: instantiated from here
prog.cpp:20:64: error: no matching function for call to 'ConcatResult<ConcatResult<ConcatenateString, ConcatenateString>, ConcatenateString>::ConcatResult(const ConcatenationExpressionBase<ConcatResult<ConcatResult<ConcatenateString, ConcatenateString>, ConcatenateString> >* const)'
prog.cpp:41:5: note: candidates are: ConcatResult<LHS, RHS>::ConcatResult(const ConcatResult<LHS, RHS>&) [with LHS = ConcatResult<ConcatenateString, ConcatenateString>, RHS = ConcatenateString, ConcatResult<LHS, RHS> = ConcatResult<ConcatResult<ConcatenateString, ConcatenateString>, ConcatenateString>]
prog.cpp:39:5: note: ConcatResult<LHS, RHS>::ConcatResult(LHS, RHS) [with LHS = ConcatResult<ConcatenateString, ConcatenateString>, RHS = ConcatenateString]
prog.cpp:20:64: error: return-statement with a value, in function returning 'void'