Consider this . There is a non-copyable, non-movable class, and there is some predicated defined for it:
struct AA
{
AA(AA const& otehr) = delete;
AA(AA && otehr) = delete;
AA& operator = (AA const& otehr) = delete;
AA& operator = (AA && otehr) = delete;
AA(int something) { }
bool good() const { return false; }
};
Because of guaranteed copy/move-elision in C++17 we can have:
auto getA() { return AA(10); }
The question is: how can one define getGoodA
, that will forward getA
in case it returned good
and will throw an exception otherwise? Is it possible at all?
auto getGoodA()
{
auto got = getA();
if (got.good()) return got; // FAILS! Move is needed.
throw std::runtime_error("BAD");
}
If we had got contract checking in C++20 you would have been able to write something like:
auto getGoodA(int i) [[post aa: aa.good()]] {
return getA(i);
}
(At least I think so - I'm not entirely clear on the type of the aa
return pseudo-variable; it would need to be a reference to the returned object in its return location.) Unfortunately contracts were removed from C++20 so it'll be some time before we can write this.
Assuming you can't modify getA
, the only way for now is to return a wrapper class from getGoodA
. The obvious solution would be unique_ptr
, but we don't actually need to perform heap allocation; a delayed-construction wrapper will do just as well :
#include <cstddef>
#include <new>
struct BB {
alignas(AA) std::byte buf[sizeof(AA)];
template<class F, class G> BB(F f, G g) { g(*new (buf) AA{f()}); }
BB(BB&&) = delete;
~BB() { reinterpret_cast<AA&>(buf).~AA(); }
operator AA&() { return reinterpret_cast<AA&>(buf); }
operator AA const&() const { return reinterpret_cast<AA const&>(buf); }
};
auto getGoodA(int i) {
return BB{
[&] { return getA(i); },
[&](AA& aa) { if (!aa.good()) throw (struct bad**){}; }};
}
Here I've given BB
a reference-style interface, allowing you to write AA& aa = getGoodA(i)
, but you could equally give it a pointer-style interface ( operator*
and operator->
) or even copy the interface of AA
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.