Reputation: 38634
I have the same question that was asked over here five years ago: Disallowing creation of the temporary objects
The reason I am asking it again is that I am specifically interested in C++11 and C++14 techniques for preventing the construction of temporaries.
One idea is to use "rvalue reference for *this":
class ScopedLock
{
public:
void enable() && = delete;
void enable() &
{
is_enabled = true;
}
~ScopedLock()
{
if (!is_enabled) {
std::cerr << "ScopedLock misuse." << std::endl;
std::terminate();
}
}
private:
bool is_enabled = false;
};
int main()
{
// OK
ScopedLock lock;
lock.enable();
// Compilation error.
ScopedLock().enable();
// std::terminate
ScopedLock();
// std::terminate
ScopedLock lock;
std::cout << "Y" << std::endl;
}
Perhaps there is a better way?
Upvotes: 1
Views: 221
Reputation: 20513
Here are C++11 versions of two great answers to the same question. I don't deserve much credit for this, so consider voting for the original answers instead.
user1773602's answer
The idea is defining a deleted function with de same name as the class:
class ScopedLock {
// ...
};
void ScopedLock(...) = delete;
The usage is unusual and this might be (very?) inconvenient:
class ScopedLock a; // OK :-| but requires keyword 'class'
ScopedLock b; // Compiler error :-(
ScopedLock(); // Compiler error :-)
Johannes Schaub - litb's answer
If you don't mind having a runtime error (like the OP seems to do) rather than a compile time error then you can try this.
The basic idea is that a temporary bound to an argument of ScopedLock
's constructor will be destroyed before or after the ScopedLock
object depending on whether the later is a temporary or not.
class ScopedLock {
bool flag_ = true;
struct Flag {
bool* flag;
~Flag() {
*flag = false;
}
};
public:
ScopedLock(Flag&& f = Flag()) {
f.flag = &flag_;
}
~ScopedLock() {
if (flag_) {
std::cerr << "ScopedLock misuse\n.";
std::terminate();
}
}
};
With this, we have
ScopedLock a; // OK
ScopedLock(); // Runtime error
Upvotes: 1