For this code
struct test {};
test f() { return test(); }
void print(test *x) {}
int main()
{
print(&f());
print(&test());
}
gcc-4.6 emits two "taking address of temporary [-fpermissive]" errors. This was introduced in 4.6, gcc-4.5 could compile it.
The reason is pretty clear and well documented. The problem is that it is a legacy code and, to compile, we have to make it work, thus, doing #pragmas around files and/or parts of code to compile them with -fpermissive. Let's say, customers are adamant not to modify the existing code (i.e. the fact of calling print() with &f() or &test() cannot be changed, not source files in general). In other words, one way or another this will be compiled, the only choice is more or less pain.
So the question is - are there any possible workarounds to make it work without doing -fpermissive in lots of places? -W flags, C++ tricks, etc.
What I meant is, the fact of calling print() with &f() or &test() cannot be changed.
If you have control over the type itself, you can always overload the reference operator, operator&, and return this from it. It's not a good thing to do in the general case, but it's fairly safe considering that you're returning the correct pointer of the correct type.
If base classes are involved, then it becomes rather more complicated. You'll need to use a virtual operator overload, and each class in the hierarchy will need to implement it separately.
You can provide a workaround by creating an extra print overload that will take a const&:
void print( test const & t ) {
print(&t); // Assuming that the function is 'print( test const * )'
// a print function should not take a non-const pointer!
}
And changing the caller to:
print( f() );
This requires code changes, but in a very limited form, so it might be acceptable. Also note that
Why not just rewrite the code to do exactly what the compiler used to do without complaining? In other words, store your temporary in a temporary (but addressable) variable.
struct test {};
test f() { return test(); }
void print(test *x) {}
int main()
{
test t1 = f();
test t2 = test();
print(&t1);
print(&t2);
}
This should behave identically to the way it did with the old compiler version. Tell the customer that the new compiler requires you to change the code to be explicit about something the compiler used to do implicitly.
It is not clear to me how much control you have over what, but the following hack seems to work:
Edit: Originally had f return a reference instead of a copy. DeadMG correctly points out this leads to undefined behavior as soon as the temporary gets used, so restored f back to returning a copy.
struct test {};
const test & test_copy (const test &t) { return t; }
#define test() test_copy(test())
test f() { return test(); }
#define f() test_copy(f())
void print(const test *) {}
int main()
{
print(&f());
print(&test());
}
The hack is to basically convert your temporaries into const references, so that the compiler will be happier. It shouldn't be made generally available, it's only purpose is to shut the compiler up. But, it doesn't really solve any underlying problems with the customer code or provided API. You could fix your API, and only resort to the hacks for certain customers:
struct test {};
test f() { return test(); }
void print(const test &) {}
#define CUSTOMER_NEEDS_HACK
#ifdef CUSTOMER_NEEDS_HACK
const test & test_copy (const test &t) { return t; }
#define test() test_copy(test())
#define f() test_copy(f())
void print(const test *t) { print(*t); }
#endif
Related
Related to my former question: Are compilers not allowed to assume const-ref parameters will stay const?
My new question is: Is there compiler-specific, non-standard extensions or syntax to tell GCC/Clang/MSVC that an object is not writable? For example, here's some fake-ish code I'd like to be able to write:
void f(const int& i) {
// At this point, compiler doesn't know if "i" can be mutated or not,
// so it assumes it can
// Fake-ish -- compiler now assumes "i" cannot be mutated and optimizes accordingly
__assume(readonly i);
// ...
}
If i is supposed to stay const for the whole function, and f() has no side effects, you could declare it with __attribute__((pure)):
int f(const int&) __attribute__((pure));
Note that it doesn't make sense for a pure function to return void, so I changed it to int.
While this does not affect how f() is compiled, it does affect the functions calling it (check it on godbolt):
#include <iostream>
int f(const int& i) __attribute__((pure));
int main() {
int i = 40;
f(i);
if (i != 40) {
std::cout << "not 40" << std::endl;
}
}
Here __attribute__((pure)) tells the compiler that f() will not change i, so the compiler will not generate the call to std::cout << ....
Without __attribute__((pure)), even if f() is declared to take a const int& i parameter, the compiler has to assume that the value of i may change, and generate the if and the call to std::cout << ... .
I do not know of non-standard ways to permit the compiler to assume immutability, but if I read the standard correctly, I think there is a standard way to do so (adapted from your other question):
void f(const int&);
struct ImmutableInt {
// it is UB to change val, because it is itself const
// not just a const reference
const int val;
};
void g3(const ImmutableInt & i) {
if (i.val == 42) f(i.val);
if (i.val == 42) f(i.val); // the compiler could assume i.val has not changed
}
The problem is, currently the compilers I checked do not make use of this knowledge to actually omit reloading the value.
I do not think there are any fundamental problems with this, because clang uses similar and more complicated reasoning about the virtual table pointer to achieve devirtualization. This reasoning is somewhat more complicated because the vptr will change during construction and is therefore not entirely const. The llvm metadata used for this is called invariant.group, but I do not know if you can set it yourself in C++.
I am in the process of boning up on my C++ (as in, attempting to get into more modern-style coding) and am looking at the delete specifier. It is my understanding that it is used to make sure that certain functionality cannot be defined or called. If I understand it correctly, this is primarily within the domain of assignment and copy. I am not quite sure what the difference is between using the delete specifier and just making those functions private.
For instance, what is the difference between:
class Foo {
private:
Foo& operator(const Foo&);
Foo(const Foo&);
};
And
class Bar {
public:
Bar& operator(const Bar&) = delete;
Bar(const Bar&) = delete;
};
In other words: what does using the delete specifier gain? Is it just to make things look nicer?
One obvious difference is that if you make the function private, then it is still accessible from within the class and any friends.
An explicitly deleted function is not usable anywhere, so you know simply from that one line that it's never used, without having to inspect the implementation.
You can make the function both private and deleted: then its participation in overload resolution is more consistent.
It's simpler.
This way, your intent is clearly stated and your compiler can outright say "calling this function is prohibited".
Otherwise you're relying on:
access control (for attempted calls from outside of the class), or
the linker giving you an "undefined reference" near the end of your build process. That's kind of okay for small programs where you can quickly find out what's going on, but for deep class hierarchies where some many-times-over encapsulated object cannot be copied but has not been deleted, good luck debugging that.
Short answer is: uses of a deleted function make the program ill-formed and you are notified at compile-time, uses of a function that is not defined end in an odd error that comes out of the linker.
As an example, there is a relevant part of the standard that states:
A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed.
Therefore, the following compiles just fine:
struct S {
void f();
};
template<typename T, void (T::*M)() = &T::f>
void g() {}
int main() {
g<S>();
}
While the code below does not:
struct S {
void f() = delete;
};
template<typename T, void (T::*M)() = &T::f>
void g() {}
int main() {
g<S>();
}
That's because in the second case the code is ill-formed and you have a compile-time error in any case, no matter if you are going to use or not M. In the second case, you get an error out of the linker only if you try to use it:
template<typename T, void (T::*M)() = &T::f>
void g() {
T t;
(t.*M)();
}
Of course, compile-time errors are much better to prevent issues. The example uses public functions, but making them private doesn't prevent from using them within the class in similar ways. That's just a toy example to show a possible difference.
A colleague asked me to look over some code he was writing and came across a problem with a particular line, which the compiler (g++) would complain about a function call not having a matching function based on its parameters.
After solving the problem in two ways (one by moving the parameter to its own variable and passing that instead, next is changing the parameter list to take it as a const reference), I had to ask this question: Why is the solution the way it is? I wasn't satisfied with writing it off as if some constructor details were being hidden away, as my colleague puts it.
As a result, I've replicated and reduced the problem to the following (compile with g++ -Wall -ansi -pedantic):
class SomeClass
{
public:
static void SomeFunction(SomeClass& sc) {}
static void SomeFunction2(const SomeClass& sc) {}
};
class SomeChild : public SomeClass {};
void testOne(void)
{
// this compiles
SomeChild sc = SomeChild();
SomeClass::SomeFunction(sc);
// this doesn't compile
//SomeClass::SomeFunction(SomeChild());
}
void testTwo(void)
{
// this compiles
SomeChild sc = SomeChild();
SomeClass::SomeFunction2(sc);
// this compiles
SomeClass::SomeFunction2(SomeChild());
}
int main(void)
{
testOne();
testTwo();
return 0;
}
I'm probably missing something very fundamental here, but can anyone explain to me why the compiler thinks there is no matching function call for the uncompilable line?
Thanks in advance.
The simple reason is that temporary values, such as the value of SomeChild(), cannot bind to non-constant lvalue references. While there's no deep technical reason for this, it's a design choice: non-constant references are usually used to modify the thing that's being referred to, and if that thing is temporary, then the modification would essentially have no lasting effect, which is almost always logic error.
Just replace 'SomeFunction2' by 'SomeFunction':
#include <iostream>
class SomeClass
{
public:
static void SomeFunction(SomeClass& sc) { std::cout << "not const" << std::endl; }
static void SomeFunction(const SomeClass& sc) { std::cout << "const" << std::endl; }
};
class SomeChild : public SomeClass {};
int main(void)
{
SomeChild sc = SomeChild();
SomeClass::SomeFunction(sc);
SomeClass::SomeFunction(SomeChild());
return 0;
}
And all is good.
Without the change you bind a temporary to a reference, that is impossible. The only alternatives are 'T', 'const T&' or a universal reference 'T&&' ( http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers)
I've got a const method in my class, which cannot be changed to non-const. In this method, I need to call a non-const method but the compiler doesn't let me do that.
Is there any way around it? Here is a simplified sample of my code:
int SomeClass::someMethod() const {
QColor saveColor = color();
setColor(QColor(255,255,255)); // Calling non-const method
// ....
setColor(saveColor); // restore color
return 1;
}
You could use const_cast on this pointer,
int SomeClass::someMethod() const {
const_cast<SomeClass*>( this )->setColor(...);// Calling non-const method
//whatever
}
but if you do that for an object that was originally declared const you run into undefined behavior.
So this:
SomeClass object;
object.someMethod();
is okay, but this:
const SomeClass object;
object.someMethod();
yields undefined behavior.
The real solution is that your const function should not be const in the first place.
One of the challenges of doing const-correctness is you can't do it halfway. It's either all or nothing. If you try to do it halfway, you end up in a tough spot like you are here. You end up with a nice const-correct class being used by some crazy old, typically legacy (or written by an old curmudgeon) code that isn't const-correct and it just doesn't work. You're left wondering if const-correctness is worth all the trouble.
I need to call a non-const method [from a const method]
You can't -- not directly. Nor should you. However, there is an alternative...
Obviously you can't call a non-const method from a const method. Otherwise, const would have no meaning when applied to member functions.
A const member function can change member variables marked mutable, but you've indicated that this is not possible in your case.
You could attempt to cast away constness by doing something like SomeClass* me = const_cast<SomeClass*>(this); but A) This will typically result in UB, or 2) It violates the whole idea of const-correctness.
One thing you could do, if what you're really trying to accomplish would support this, is to create a non-const proxy object, and do nonconst-y stuff with that. To wit:
#include <iostream>
#include <string>
using namespace std;
class Gizmo
{
public:
Gizmo() : n_(42) {};
void Foo() const;
void Bar() { cout << "Bar() : " << n_ << "\n"; }
void SetN(int n) { n_ = n; };
int GetN() const { return n_; }
private:
int n_;
};
void Gizmo::Foo() const
{
// we want to do non-const'y things, so create a proxy...
Gizmo proxy(*this);
int save_n = proxy.GetN();
proxy.SetN(save_n + 1);
proxy.Bar();
proxy.SetN(save_n);
}
int main()
{
Gizmo gizmo;
gizmo.Foo();
}
If you require to change some internal state inside a const-method you can also declare the affected state mutable:
class Foo {
public:
void doStuff() const { bar = 5; }
private:
mutable int bar;
};
This is intended for cases where you have stuff like mutexes as members of your class. Acquiring and releasing a mutex does not affect client-visible state, but is technically forbidden in a const-method. The solution is to mark the mutex mutable. Your case looks similar, although I think your class requires some refactoring for this solution to be applicable.
Also, you might want to read this answer to see how you can make this temporary state-change exception-safe using RAII.
How to call a non-const method from a const method?
You should not. You might run into undefined behaviour if you cast away the const-ness of this, using const_cast. The usage ofconst_cast will shut the compiler's mouth up, but that isn't a solution. If you need to do, then it means the const function should not be const in the first place. Make it non-const.
Or, you should do something else, which would not require you to call non-const function from const function. Like, don't call setColor function? Like, split the const function into more than one functions (if you can do that)? Or something else?
In your particular case, if setColor only sets some member variable, say m_color, then you can declare it mutable:
mutable QColor m_color;
and then set it in your const function, without calling setColor function, and without doing const_cast.
If I do this:
// In header
class Foo {
void foo(bar*);
};
// In cpp
void Foo::foo(bar* const pBar) {
//Stuff
}
The compiler does not complain that the signatures for Foo::foo do not match. However if I had:
void foo(const bar*); //In header
void Foo::foo(bar*) {} //In cpp
The code will fail to compile.
What is going on?
I'm using gcc 4.1.x
In the first, you've promised the compiler, but not other users of the class that you will not edit the variable.
In your second example, you've promised other users of the class that you will not edit their variable, but failed to uphold that promise.
I should also note that there is a distinct difference between
bar* const variable
and
const bar* variable
and
const bar* const variable
In the first form, the pointer will never change, but you can edit the object that is pointed to. In the second form, you can edit the pointer(point it to another object), but never the variable that it points to. In the final form, you will neither edit the pointer, nor the object it points to. Reference
To add a bit more of a clarification to the question stated, you can always promise MORE const than less. Given a class:
class Foo {
void func1 (int x);
void func2 (int *x);
}
You can compile the following implementation:
Foo::func1(const int x) {}
Foo::func2(const int *x) {}
or:
Foo::func1(const int x) {}
Foo::func2(const int* const x) {}
without any problems. You've told your users that you may possibly edit their variables. In your implementation, you've told the compiler that this particular implementation will not edit those variables, even though the told the users you might. You haven't broken a promise to the user, and so the code compiles.
See this question, this question, and this question.
Basically, the const only means that the function will not modify the pointer's value. The pointers contents are not const, the same as the header's signature.
The const keyword in the first example is meaningless. You are saying that you don't plan on changing the pointer. However, the pointer was passed by value and so it dos not matter if you change it or not; it will not effect the caller. Similarly, you could also do this:
// In header
class Foo {
void foo( int b );
};
// In cpp
void Foo::foo( const int b ) {
//Stuff
}
You can even do this:
// In header
class Foo {
void foo( const int b );
};
// In cpp
void Foo::foo( int b ) {
//Stuff
}
Since the int is passed by value, the constness does not matter.
In the second example you are saying that your function takes a pointer to one type, but then implement it as taking a pointer to another type, therefore it fails.
So the second const in:
void Foo::foo(const bar* const);
Is not part of the method signature?
This is simpler to understand with a variable type other than a pointer. For example, you can have the following function declaration:
void foo( int i );
The definition can look like this:
void foo( const int i ) { ... }
Whether the variable 'i' is const or not on the definition side is an implementation detail. It has no impact for the clients of that function.
It probably doesn't care much about void Foo::foo(bar* const pBar) because how you treat the pointer itself (const or not) doesn't matter one bit outside of the routine. The C rules say that no change to pBar will travel outside of foo either way.
However, if it is (const bar* pBar), that makes a difference, because it means the compiler is not to allow callers to pass in pointers to non-const objects.
In the former, the const doesn't affect the interface, only the implementation. You are saying to the compiler, "I am not going to change the value of the bar* within this function". You can still change what is pointed to by the pointer. In the latter, you are telling the compiler (and all callers) that you will not change the bar structure that the bar* points to.