How to disallow temporaries
Another macro-based solution:
#define Foo class Foo
The statement Foo("hi");
expands to class Foo("hi");
, which is ill-formed; but Foo a("hi")
expands to class Foo a("hi")
, which is correct.
This has the advantage that it is both source- and binary-compatible with existing (correct) code. (This claim is not entirely correct - please see Johannes Schaub's Comment and ensuing discussion below: "How can you know that it is source compatible with existing code? His friend includes his header and has void f() { int Foo = 0; } which previously compiled fine and now miscompiles! Also, every line that defines a member function of class Foo fails: void class Foo::bar() {}")
Disallowing creation of the temporary objects
Edit: As j_random_hacker notes, it is possible to force the user to declare a named object in order to take out a lock.
However, even if creation of temporaries was somehow banned for your class, then the user could make a similar mistake:
// take out a lock:
if (m_multiThreaded)
{
CSingleLock c(&m_criticalSection, TRUE);
}
// do other stuff, assuming lock is held
Ultimately, the user has to understand the impact of a line of code that they write. In this case, they have to know that they're creating an object and they have to know how long it lasts.
Another likely mistake:
CSingleLock *c = new CSingleLock(&m_criticalSection, TRUE);
// do other stuff, don't call delete on c...
Which would lead you to ask "Is there any way I can stop the user of my class from allocating it on the heap"? To which the answer would be the same.
In C++0x there will be another way to do all this, by using lambdas. Define a function:
template <class TLock, class TLockedOperation>
void WithLock(TLock *lock, const TLockedOperation &op)
{
CSingleLock c(lock, TRUE);
op();
}
That function captures the correct usage of CSingleLock. Now let users do this:
WithLock(&m_criticalSection,
[&] {
// do stuff, lock is held in this context.
});
This is much harder for the user to screw up. The syntax looks weird at first, but [&] followed by a code block means "Define a function that takes no args, and if I refer to anything by name and it is the name of something outside (e.g. a local variable in the containing function) let me access it by non-const reference, so I can modify it.)
Can I forbid temporary objects as parameters?
If your parameter is not const
, the function won't accept temporaries.
If your parameter is const
, the function accepts both temporary and regular objects.
But if you want to prevent that, you can use the following
struct Object{};
void foo(const Object& o) {
/*only query o, don't alter it*/
}
void foo(Object&& ) = delete;
int main() {
Object o;
foo(o); // allow this
foo(Object{}); // but disallow this
}
Live
How to disallow temporaries in functions taking const references?
You can provide an additional overload that's a better matches for temporaries and then delete it. For example :
#include <string>
void foo(const std::string &) {}
void foo(std::string &&) = delete;
int main()
{
std::string world = "World";
foo("Hello"); // Doesn't compile, wants to use foo(std::string &&)
foo(world); // Compiles
}
How to disable instantiating a temporary class?
You seem to want to prevent users from using auto
on a particular type. That's not possible in any version of C++. If it is legal C++ for a user to write T t = <expr>;
, where T
is the type of <expr>
, then it will be legal for a user to write auto t = <expr>;
(ignoring class data members). Just as you cannot forbid someone from passing <expr>
to a template function using template argument deduction.
Anything you do to prevent auto
usage will also inhibit some other usage of the type.
Related Topics
Using Char16_T and Char32_T in I/O
How to Count Cameras in Opencv 2.3
How to Use Unordered_Set with Custom Types
How to Load a Bmp on Glut to Use It as a Texture
Is Casting Std::Pair<T1, T2> Const& to Std::Pair<T1 Const, T2> Const& Safe
Why Can't We Declare Object of a Class Inside the Same Class
How to Avoid Errors While Using Crtp
Why Is Iterating 2D Array Row Major Faster Than Column Major
Incomplete Class Usage in Template
Forward Declaration with Vector of Class Type - Pointer to Incomplete Class Type Not Allowed
Open File with Fopen, Given Absolute Path on Windows
Why Use #Ifndef Class_H and #Define Class_H in .H File But Not in .Cpp
Coding Practices Which Enable the Compiler/Optimizer to Make a Faster Program
Cmake: Project Structure with Unit Tests
Is There a C++ Gdb Gui for Linux
How Exactly Is Std::String_View Faster Than Const Std::String&