Methods in C++14 can tell whether they're called on an L-value or an R-value:
struct A{
A() { puts("Ctor"); }
void m() const & { puts("L-value"); }
void m() const && { puts("R-value"); }
};
int main(){
A a; //Ctor
a.m() //L-value
A().m(); //Ctor; R-value
}
Can a ctor tell which type it's constructing? Can I completely disable the construction of L-values from my class?
I have a proxy class (several, actually), which should always convert to something else. Using it without converting is an error. I can detect that error at runtime, e.g., by adding a bool used_ = 0;
member #ifndef NDEBUG;
and setting it in my user-specified cast, and then doing assert(used_)
in the proxy class's Dtor
, however it would be much nicer if I could get to compiler to prevent instatiation of L-value
instances of that proxy in the first place:
auto x = Proxy().method1().method2(); // no
Proxy p; // no
Target x = Proxy(); //yes
Target x = Proxy().method1().method2(); //yes
Can I do something like that with C++14?
struct temporary_only {
static temporary_only make() { return {}; }
temporary_only(temporary_only&&)=delete;
int get()&& { return 3; }
private:
temporary_only() {}
};
int main() {
//temporary_only x; // illegal
std::cout << temporary_only::make().get() << '\n'; // legal
}
live example.
We disable all public ctors (including copy/move), so nobody can create a temporary_only
except via temporary_only::make
(an rvalue).
Note that
temporary_only&& a = temporary_only::make();
still works. Here we have an rvalue bound to an rvalue reference, and that rvalue reference is itself an lvalue with a multi-line lifetime (scope lifetime). This cannot be stopped.
Why, of course:
#include <iostream>
using namespace std;
class B;
class A
{
public:
A(B&& b) {}
A(const B&) = delete;
};
class B {};
int main()
{
B b;
// A a1; <- error
// A a2 = b; // <- error
A a3 = move(b); // <- fine
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With