Consider the following piece of C++ code:
class Foo {
public:
int a;
};
class Bar {
public:
int w = 1;
bool are_foos_equal(Foo* f1, Foo* f2) { return f1->a * w == f2->a * w; }
struct FooHash { size_t operator () (Foo* f) const { return f->a; } };
struct FooEqual {
bool operator () (Foo* f1, Foo* f2) const {
return are_foos_equal(f1, f2);
}
};
std::unordered_set<Foo*, FooHash, FooEqual> fooset;
};
Now, this doesn't compile because in the operator () of FooEqual I cannot invoke non-static are_foos_equal.
My question is: is it possible for fooset to use are_foos_equal somehow? I know that I could just make are_foos_equal static but the example code I gave is just so that I could state my problem which, unfortunately, occured in a much bigger project, and even if that means that the design is somewhat wrong, I'd like to rescue it by some hacks, if possible.
EDIT
I added a non-static member variable w to Bar to emphasize "non-staticness" of are_foos_equal.
Move are_foos_equal() outside of the class and make it a free function. It doesn't make sense that it should be a member of Bar. Example:
class Foo {
public:
int a;
};
bool are_foos_equal(Foo* f1, Foo* f2)
{return f1->a == f2->a;}
class Bar {
public:
struct FooHash { size_t operator () (Foo* f) const { return f->a; } };
struct FooEqual {
bool operator () (Foo* f1, Foo* f2) const {
return are_foos_equal(f1, f2);
}
};
std::unordered_set<Foo*, FooHash, FooEqual> fooset;
};
You could maintain a reference to the parent Bar object in FooEqual:
Bar() : fooset{10, FooHash{}, FooEqual{*this}}
{}
struct FooEqual {
Bar& parent;
bool operator () (Foo* f1, Foo* f2) const {
return parent.are_foos_equal(f1, f2);
}
};
Because of how the constructors are declared in std::unordered_set you need to provide a bucket count, which is a bit unfortunate. You could get the default from a default-constructed std::unordered_set if you felt like it.
The correct option would definitely be to make are_foos_equal static. I would strongly suggest doing this instead of a hack. The larger the project, the cleaner it needs to be so that it doesn't devolve into an unmaintainable mess.
But if that is seriously not an option, I see a few other possibilities:
Create a Bar object on the fly inside FooEqual:
return Bar().are_foos_equal(f1, f2);
Have FooEqual store a static Bar object for this purpose:
bool operator() (Foo* f1, Foo* f2) const {
static Bar bar;
return bar.are_foos_equal(f1, f2);
}
Invoke Undefined Behaviour, invoke are_foos_equal on a null pointer and hope that it doesn't do anything bad. I strongly discourage this:
return static_cast<Bar*>(nullptr)->are_foos_equal(f1, f2);
Here it could be trivial, because are_foos_equal could be static, as it neither use not change anything in this
=> first way just declare are_foos_equal static.
Alternatively, if the called function cannot be static because it uses or changes it object, you will have to change FooEqual to contain a Bar object (or a pointer or reference to it) . Because C++ is not java: inner classes have no hidden pointer to an object of enclosing class.
=> second way add a reference to a Bar in FooEqual and set it at construction time:
struct FooEqual {
const Bar &bar;
FooEqual(const Bar& bar): bar(bar) {};
bool operator () (Foo* f1, Foo* f2) const {
return bar.are_foos_equal(f1, f2);
}
Related
Is the following code considered safe?
Foo& GetFoo()
{
static std::once_flag fooInitFlag;
static Foo f;
std::call_once(fooInitFlag, [&Foo]()
{
Foo.Init();
});
return std::ref(f);
}
Instead of this posted code:
Foo& GetFoo()
{
static std::once_flag fooInitFlag;
static Foo f;
std::call_once(fooInitFlag, [&Foo]()
{
Foo.Init();
});
return std::ref(f);
}
do this:
struct Initialized_foo
{
Foo item;
Initialized_foo() { item.Init(); }
};
auto get_foo()
-> Foo&
{
static Initialized_foo the_foo;
return the_foo.item;
}
It's not more safe, but it's simpler, and hence more safe against inadvertently introduced bugs.
Note that the standard guarantees a single initialization here, even in the context of multi-threading.
Better, ideally each Foo insteance should be properly initialized by the Foo constructor, not by an Init method. But that's not always possible to arrange.
You asked:
Is the following code considered safe?
The answer is yes.
Another implementation:
// Not exposed to the outside.
static Foo& getInitializedFoo();
{
static Foo f;
f.Init();
return f;
}
Foo& GetFoo()
{
static Foo& f = getInitializedFoo();
return f;
}
I have been using this method without any problem, but I want to make sure if this is a totally allowed approach or I am just being lucky!
class A
{
public:
void bar()
{
foo(*this);
}
};
void foo(A &a)
{
}
thank you
As long as void Foo(A&) is (forward) declared so that A::bar knows about its existance it's fully valid and 100% allowed.
Notes
Is there anywhere I may not dereference this?
Not really, but there are a few issues you should know about. If you want to use *this in the initialization list of a constructing object please remember that you are not allowed to access virtual or uninitialized members of that object through it; neither directly nor indirectly.
if the member-function is declared const only functions taking a const (reference) are allowed to be called using a dereferenced this-pointer, see the below example.
void func (struct Obj&);
void func (struct Obj const&);
struct Obj {
void bar () const {
func (*this);
}
void bar () {
func (*this);
}
};
int
main (int argc, char *argv[])
{
Obj a;
Obj const b;
a.bar (); /* func (Obj &) */
b.bar (); /* func (Obj const&) */
}
Yes, it's allowed. Note that from a const method, you can pass *this only to functions accepting const parameters:
class B;
void foo(B&);
void bar(B const&);
class B {
void meow() const {
bar(*this); //OK
foo(*this); //ERROR
}
};
Yes, it is perfectly legal. This is what you do when you write return *this; in some operators (like assignment operator).
This is perfectly fine, and a common pattern for "I want some other function or object to know about this object".
Just make sure that the reference isn't saved beyond the lifetime of the one passed in.
I want to return a signle object from a method call which contains multiple objects created in the method.
Results calculate() {
Foo f;
Bar b;
...
Results r(f, b);
return r;
}
class Results {
private:
?
public:
Results(Foo& f, Bar& b);
Foo? getFoo();
Bar? getBar();
}
a) Should Results member variables be pointers?
private:
Foo* foo;
Bar* bar;
public:
Results(Foo& f, Bar& b) {
this->foo = &f;
this->bar = &b;
}
b) Should getFoo return Foo, Foo& or Foo*?
Use C++11's tuples(or boost's, otherwise), you're basically reimplementing them:
#include <tuple>
std::tuple<Foo, Bar> calculate() {
Foo f;
Bar b;
...
return std::make_tuple(f, b);
}
void test() {
Foo f;
Bar b;
std::tie(f, b) = calculate();
}
Note that this could be easily extended to return more than 2 objects. That's why I used std::tuple rather than std::pair as mentioned in another answer.
No, don't do it this way. Because in calculate(), Foo f and Bar b are local objects, which will go away, when you return from this function. Copy f and b into Results.
class Results {
private:
Foo foo;
Bar bar;
public:
Results(const Foo& f, const Bar& b) : foo(f), bar(b) {}
const Foo &getFoo() const { return foo; }
const Bar &getBar() const { return bar; }
}
An easier way could be to use a std::pair and return that instead
std::pair<Foo, Bar> calculate() {
Foo f;
Bar b;
...
return std::make_pair(f, b);
}
a) No. By initializing the values in calculate(), these variables "die" when the function finished executing. This way, the pointers you initialized before will point to an empty space.
b) Considering the private members not to be pointers, you can do this as you want. If you want the data to "stay" inside the object, you may take pointers or references (does not matter which one). Take "normal" variables otherwise.
a) The results member variables should be held by value. Otherwise you return the addresses (or references) of local, out-of-scope data.
b) getFoo should return a const reference to the object, or return by value, in case of POD types.
That said, consider changing your interface to accept i/o parameters of the types Foo& and Bar&, populate the variables inside and not return them. This would avoid two copies of the returned values, which are necessary otherwise.
You can also replace your Results class with a std::tuple:
std::tuple<Foo,Bar> calculate() {
Foo f;
Bar b;
...
return std::tuple(f,b);
}
// client code:
Foo foo;
Bar bar;
std::tie(foo, bar) = calculate();
Edit: If you do not use C++11 (for std::tuple) consider boost::tuple instead.
I'm still a bit uncertain what you're trying to achieve, but currently you'd run into trouble:
a and b are on the stack in calculate, you essentially return pointers to them. But as soon as calculate is finished and a and b go out of scope, you have wild pointers. That's very bad.
Create smart pointers and return them in an object if you have more return values.
Or pass pointers to a and b to calculate and create the objects on the heap with new in calculate. But be aware that you have to delete them by yourself otherwise you end up with memory leaks.
So basically, if you have more than two objects in result, then add a smart pointer like std::auto_ptr or std::shared_ptr (or if you don't use C++11 boost::shared_ptr)
For a class Foo, is there a way to disallow constructing it without giving it a name?
For example:
Foo("hi");
And only allow it if you give it a name, like the following?
Foo my_foo("hi");
The lifetime of the first one is just the statement, and the second one is the enclosing block. In my use case, Foo is measuring the time between constructor and destructor. Since I never refer to the local variable, I often forget to put it in, and accidentally change the lifetime. I'd like to get a compile time error instead.
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() {}")
How about a little hack
class Foo
{
public:
Foo (const char*) {}
};
void Foo (float);
int main ()
{
Foo ("hello"); // error
class Foo a("hi"); // OK
return 1;
}
Make the constructor private but give the class a create method.
This one doesn't result in a compiler error, but a runtime error. Instead of measuring a wrong time, you get an exception which may be acceptable too.
Any constructor you want to guard needs a default argument on which set(guard) is called.
struct Guard {
Guard()
:guardflagp()
{ }
~Guard() {
assert(guardflagp && "Forgot to call guard?");
*guardflagp = 0;
}
void *set(Guard const *&guardflag) {
if(guardflagp) {
*guardflagp = 0;
}
guardflagp = &guardflag;
*guardflagp = this;
}
private:
Guard const **guardflagp;
};
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics are:
Foo f() {
// OK (no temporary)
Foo f1("hello");
// may throw (may introduce a temporary on behalf of the compiler)
Foo f2 = "hello";
// may throw (introduces a temporary that may be optimized away
Foo f3 = Foo("hello");
// OK (no temporary)
Foo f4{"hello"};
// OK (no temporary)
Foo f = { "hello" };
// always throws
Foo("hello");
// OK (normal copy)
return f;
// may throw (may introduce a temporary on behalf of the compiler)
return "hello";
// OK (initialized temporary lives longer than its initializers)
return { "hello" };
}
int main() {
// OK (it's f that created the temporary in its body)
f();
// OK (normal copy)
Foo g1(f());
// OK (normal copy)
Foo g2 = f();
}
The case of f2, f3 and the return of "hello" may not be wanted. To prevent throwing, you can allow the source of a copy to be a temporary, by resetting the guard to now guard us instead of the source of the copy. Now you also see why we used the pointers above - it allows us to be flexible.
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
Foo(Foo &&other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
Foo(const Foo& other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics for f2, f3 and for return "hello" are now always // OK.
A few years ago I wrote a patch for the GNU C++ compiler which adds a new warning option for that situation. This is tracked in a Bugzilla item.
Unfortunately, GCC Bugzilla is a burial ground where well-considered patch-included feature suggestions go to die. :)
This was motivated by the desire to catch exactly the sort of bugs that are the subject of this question in code which uses local objects as gadgets for locking and unlocking, measuring execution time and so forth.
As is, with your implementation, you cannot do this, but you can use this rule to your advantage:
Temporary objects cannot be bound to non-const references
You can move the code from the class to an freestanding function which takes a non-const reference parameter. If you do so, You will get a compiler error if an temporary tries to bind to the non-const reference.
Code Sample
class Foo
{
public:
Foo(const char* ){}
friend void InitMethod(Foo& obj);
};
void InitMethod(Foo& obj){}
int main()
{
Foo myVar("InitMe");
InitMethod(myVar); //Works
InitMethod("InitMe"); //Does not work
return 0;
}
Output
prog.cpp: In function ‘int main()’:
prog.cpp:13: error: invalid initialization of non-const reference of type ‘Foo&’ from a temporary of type ‘const char*’
prog.cpp:7: error: in passing argument 1 of ‘void InitMethod(Foo&)’
Simply don't have a default constructor, and do require a reference to an instance in every constructor.
#include <iostream>
using namespace std;
enum SelfRef { selfRef };
struct S
{
S( SelfRef, S const & ) {}
};
int main()
{
S a( selfRef, a );
}
No, I'm afraid this isn't possible. But you could get the same effect by creating a macro.
#define FOO(x) Foo _foo(x)
With this in place, you can just write FOO(x) instead of Foo my_foo(x).
Since the primary goal is to prevent bugs, consider this:
struct Foo
{
Foo( const char* ) { /* ... */ }
};
enum { Foo };
int main()
{
struct Foo foo( "hi" ); // OK
struct Foo( "hi" ); // fail
Foo foo( "hi" ); // fail
Foo( "hi" ); // fail
}
That way you can't forget to name the variable and you can't forget to write struct. Verbose, but safe.
Declare one-parametric constructor as explicit and nobody will ever create an object of that class unintentionally.
For example
class Foo
{
public:
explicit Foo(const char*);
};
void fun(const Foo&);
can only be used this way
void g() {
Foo a("text");
fun(a);
}
but never this way (through a temporary on the stack)
void g() {
fun("text");
}
See also: Alexandrescu, C++ Coding Standards, Item 40.
For a class Foo, is there a way to disallow constructing it without giving it a name?
For example:
Foo("hi");
And only allow it if you give it a name, like the following?
Foo my_foo("hi");
The lifetime of the first one is just the statement, and the second one is the enclosing block. In my use case, Foo is measuring the time between constructor and destructor. Since I never refer to the local variable, I often forget to put it in, and accidentally change the lifetime. I'd like to get a compile time error instead.
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() {}")
How about a little hack
class Foo
{
public:
Foo (const char*) {}
};
void Foo (float);
int main ()
{
Foo ("hello"); // error
class Foo a("hi"); // OK
return 1;
}
Make the constructor private but give the class a create method.
This one doesn't result in a compiler error, but a runtime error. Instead of measuring a wrong time, you get an exception which may be acceptable too.
Any constructor you want to guard needs a default argument on which set(guard) is called.
struct Guard {
Guard()
:guardflagp()
{ }
~Guard() {
assert(guardflagp && "Forgot to call guard?");
*guardflagp = 0;
}
void *set(Guard const *&guardflag) {
if(guardflagp) {
*guardflagp = 0;
}
guardflagp = &guardflag;
*guardflagp = this;
}
private:
Guard const **guardflagp;
};
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics are:
Foo f() {
// OK (no temporary)
Foo f1("hello");
// may throw (may introduce a temporary on behalf of the compiler)
Foo f2 = "hello";
// may throw (introduces a temporary that may be optimized away
Foo f3 = Foo("hello");
// OK (no temporary)
Foo f4{"hello"};
// OK (no temporary)
Foo f = { "hello" };
// always throws
Foo("hello");
// OK (normal copy)
return f;
// may throw (may introduce a temporary on behalf of the compiler)
return "hello";
// OK (initialized temporary lives longer than its initializers)
return { "hello" };
}
int main() {
// OK (it's f that created the temporary in its body)
f();
// OK (normal copy)
Foo g1(f());
// OK (normal copy)
Foo g2 = f();
}
The case of f2, f3 and the return of "hello" may not be wanted. To prevent throwing, you can allow the source of a copy to be a temporary, by resetting the guard to now guard us instead of the source of the copy. Now you also see why we used the pointers above - it allows us to be flexible.
class Foo {
public:
Foo(const char *arg1, Guard &&g = Guard())
:guard()
{ g.set(guard); }
Foo(Foo &&other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
Foo(const Foo& other)
:guard(other.guard)
{
if(guard) {
guard->set(guard);
}
}
~Foo() {
assert(!guard && "A Foo object cannot be temporary!");
}
private:
mutable Guard const *guard;
};
The characteristics for f2, f3 and for return "hello" are now always // OK.
A few years ago I wrote a patch for the GNU C++ compiler which adds a new warning option for that situation. This is tracked in a Bugzilla item.
Unfortunately, GCC Bugzilla is a burial ground where well-considered patch-included feature suggestions go to die. :)
This was motivated by the desire to catch exactly the sort of bugs that are the subject of this question in code which uses local objects as gadgets for locking and unlocking, measuring execution time and so forth.
As is, with your implementation, you cannot do this, but you can use this rule to your advantage:
Temporary objects cannot be bound to non-const references
You can move the code from the class to an freestanding function which takes a non-const reference parameter. If you do so, You will get a compiler error if an temporary tries to bind to the non-const reference.
Code Sample
class Foo
{
public:
Foo(const char* ){}
friend void InitMethod(Foo& obj);
};
void InitMethod(Foo& obj){}
int main()
{
Foo myVar("InitMe");
InitMethod(myVar); //Works
InitMethod("InitMe"); //Does not work
return 0;
}
Output
prog.cpp: In function ‘int main()’:
prog.cpp:13: error: invalid initialization of non-const reference of type ‘Foo&’ from a temporary of type ‘const char*’
prog.cpp:7: error: in passing argument 1 of ‘void InitMethod(Foo&)’
Simply don't have a default constructor, and do require a reference to an instance in every constructor.
#include <iostream>
using namespace std;
enum SelfRef { selfRef };
struct S
{
S( SelfRef, S const & ) {}
};
int main()
{
S a( selfRef, a );
}
No, I'm afraid this isn't possible. But you could get the same effect by creating a macro.
#define FOO(x) Foo _foo(x)
With this in place, you can just write FOO(x) instead of Foo my_foo(x).
Since the primary goal is to prevent bugs, consider this:
struct Foo
{
Foo( const char* ) { /* ... */ }
};
enum { Foo };
int main()
{
struct Foo foo( "hi" ); // OK
struct Foo( "hi" ); // fail
Foo foo( "hi" ); // fail
Foo( "hi" ); // fail
}
That way you can't forget to name the variable and you can't forget to write struct. Verbose, but safe.
Declare one-parametric constructor as explicit and nobody will ever create an object of that class unintentionally.
For example
class Foo
{
public:
explicit Foo(const char*);
};
void fun(const Foo&);
can only be used this way
void g() {
Foo a("text");
fun(a);
}
but never this way (through a temporary on the stack)
void g() {
fun("text");
}
See also: Alexandrescu, C++ Coding Standards, Item 40.