I'm in the process of updating performance critical libraries to use restrict, as implemented in C++11 by g++ and MSVC with the keyword __restrict. This seems to be the most-standard-extension, so I'll use restrict and __restrict interchangeably.
restrict is a C99 keyword, but nevertheless compilers have defined important uses for it in C++.
This post intends to be a "question" asking about what each C++-specific use is and what it means, followed by a CW answer answering it. Feel free to add/check/edit. So: "Help! What do these C++ uses of the restrict keyword mean?"
Qualifying this (restrict a method):
void Foo::method(int*__restrict a) __restrict { /*...*/ }
Restrict a reference:
int&__restrict x = /*...*/;
Restrict inside a template:
std::vector<float*__restrict> x;
Restrict a member/field. This technically also applies to C's struct, but it comes up as an issue in C++ more often than it does in C:
class Foo final { public: int*__restrict field; };
Qualifying this (restrict a method):
This means that the this pointer is restricted. This one major consequence:
The method can't operate on itself as data, e.g.:
void Foo::method(Foo*__restrict other) __restrict { /*...*/ }
In that example, this might otherwise alias other. restrict is saying that you can't call this method with itself as an argument.
Note: it is okay to access or change the object, even through a field. The reason why is that the following are functionally identical:
void Foo::method1(void) __restrict { field=6; }
void Foo::method2(void) __restrict { this->field=6; }
In that example, this is not aliased with anything.
Restrict a reference:
It appears to mean exactly that--that the reference is restricted. What this exactly does and whether it's useful is another matter. Someone on this thread claims compilers can statically determine aliasing for references, and so the keyword is supposedly useless. This question was also asked about whether it should be used, but the answer "vendor specific" is hardly helpful.
There is precedent on this question. In short, in function f, the compiler knows that a.field and b.field are not aliased:
class Foo final {
int*__restrict field;
};
int f(Foo a, Foo b) { /*...*/ }
This will often be the case, assuming a!=b--for example, if field is allocated and destroyed by the constructor/destructor of Foo. Note that if field is a raw array, it will always be true and so the restrict keyword is unnecessary (and impossible) to apply.
Related
template<typename T> struct Derived: T
{
/*static*/ int foo(int x) { return T::foo(x) + 1; }
};
If T::foo(int x) is static then Derived<T>::foo(int x) should also be static. Otherwise Derived<T>::foo(int x) should be non-static.
Is there a way to let the compiler take care of this?
No, you cannot propagate staticness in the sense you ask. Incidentally, you could also ask the same thing about const:
int foo(int x) { return bar(x) + 1; } // Infer that foo is const because bar is
C++ specifiers are meant to convey intent about the interface, on which users can rely even if the implementation changes:
static int foo(x); // This method does not require an object
int foo(x) const; // This method will not modify the object
In case - through templates, for example - the implementation may vary, your interface must reflect the lowest common denominator. For const, for example, methods need to be non-const. For static, which is your question, you cannot declare static.
Note that this is not a huge imposition. Even if a method is static, you can still call it using with object semantics. So, in your case, you'll have to just use object semantics. In particular, regarding your clarification in the comments
If allocator is static then container doesn't need to hold it's pointer. So decorators must preserve staticness.
note that decorators can also not preserve staticness, because containers can hold pointers in any case, and call them via object notation, regardless of their constness.
Use below construct:
static_assert(std::is_same<decltype(&Derived::foo), decltype(&T::foo)>::value or
(std::is_member_function_pointer<decltype(&Derived::foo)>::value and
std::is_member_function_pointer<decltype(&T::foo)>::value),
"Derived::foo & T::foo are not having same static-ness");
I have tested quickly with my g++ and it works fine.
What it does
Takes address of both the methods and if they are comparable then
they must be static. This means that the methods signatures are
expected to be same (as implied in your example).
If (1) fails then check if both the foo are function pointers of
their respective classes types. Here no strictness of type, but you can impose with some more meta programming. Leaving up to you.
If both of above fails, then the compiler gives an error. This static_assert can be put within class Derived.
Notes: (1) If Derived::foo is static & T::foo is not then anyways, it gives error. (2) or & and are official keywords of C++. If certain compilers like MSVC doesn't support then use || & && respectively.
In C++ the following code gives a compiler error:
void destruct1 (int * item)
{
item->~int();
}
This code is nearly the same, I just typedef the int to another type and something magic happens:
typedef int myint;
void destruct2 (myint * item)
{
item->~myint();
}
Why does the second code work? Does an int get a destructor just because it has been typedefed?
In case you wonder why one ever would like to do this: This comes from refactoring C++ code. We're removing the standard heap and replacing it with selfmade pools. This requires us to call placement-new and the destructors. I know that calling destructors for primitive types is useless, but we want them in the code nevertheless in case we later replace PODs with real classes.
Finding out that naked int's don't work but typedefed ones do was quite a surprise.
Btw - I have a solution that involves template-functions. We just typedef inside the template and everything is fine.
It's the reason that makes your code work for generic parameters. Consider a container C:
template<typename T>
struct C {
// ...
~C() {
for(size_t i = 0; i<elements; i++)
buffer[i].~T();
}
};
It would be annoying to introduce special cases for built-in types. So C++ allows you to do the above, even if T happens to equal to int. The holy Standard says in 12.4 p15:
The notation for explicit call of a destructor can be used for any scalar type name. Allowing this makes it possible to write code without having to know if a destructor exists for a given type.
The difference between using a plain int and a typedef'ed int is that they are syntactically different things. The rule is, that in a destructor call, the thing after the ~ is a type-name. int is not such a thing, but a typedef-name is. Look it up in 7.1.5.2.
I am trying to implement the use of a C++ library within my project that has not used const modifiers on its access functions. Up until now I have been using const in all of my code but this new library is causing two main problems:
Functions where the arguments are passed as const references cannot use the argument's access functions if these arguments are of a type defined by the library.
Classes with member objects of types defined by the library cannot use the access functions of these objects within a const function.
What is the best way to overcome this issue? The easiest solution would be to simply remove all use of const from my code but that would be quite frustrating to do.
Additional info: In this case I do have access to the source code and can see that the access functions do not modify anything. I omitted this information as I was interested in the more general case as well. For my scenario, const_cast appears to be the way to go
PS The library writer is not evil! It is more a bit of rough and ready code that he has kindly open sourced. I could ditch the library and use something more professional as others have noted. However, for this small time-constrained project, the simplicity of the interface to this library has made it the best choice.
How easy is it to tell whether the functions in the library actually modify anything or not?
If it's easy to tell, and they don't, then you can const_cast your const pointer/reference to non-const and call the library function. You might want to throw a wrapper around the library classes to do this for you, which is tedious and verbose but gets that code out of your classes. This wrapper could perhaps be a subclass that adds some const accessors, depending whether the way you use the library class allows that to work.
If it's hard to tell, or they do modify things, then you need to use non-const instances and references to the library classes in your code. mutable can help with those of type (2), but for those of type (1) you just need to pass non-const arguments around.
For an example of why it might be hard, consider that the library author might have written something like this:
struct Foo {
size_t times_accessed;
int value;
int get() {
++times_accessed;
return value;
}
};
Now, if you const_cast a const instance of Foo and call get(), you have undefined behavior[*]. So you have to be sure that get really doesn't modify the object it's called on. You could mitigate this a bit, by making sure that you never create any const instances of Foo, even though you do take const references to non-const instances. That way, when you const_cast and call get you at least don't cause UB. It might make your code confusing, that fields keep changing on objects that your functions claim not to modify.
[*] Why is it undefined behavior? It has to be, in order that the language can guarantee that the value of a const object never changes in a valid program. This guarantee allows the compiler to do useful things. For example it can put static const objects in read-only data sections, and it can optimize code using known values. It also means that a const integer object with a visible initializer is a compile-time constant, which the standard makes use of to let you use it as the size of an array, or a template argument. If it wasn't UB to modify a const object, then const objects wouldn't be constant, and these things wouldn't be possible:
#include <iostream>
struct Foo {
int a;
Foo(int a) : a(a) {}
};
void nobody_knows_what_this_does1(const int *p); // defined in another TU
void nobody_knows_what_this_does2(const int *p); // defined in another TU
int main() {
const Foo f(1);
Foo g(1);
nobody_knows_what_this_does1(&f.a);
nobody_knows_what_this_does2(&g.a);
int x;
if (std::cin >> x) {
std::cout << (x / f.a); // Optimization opportunity!
std::cout << (x / g.a); // Cannot optimize!
}
}
Because f is a const object, and hence f.a is a const object, the optimizer knows that f.a has value 1 when it's used at the end of the function. It could, if it chose, optimize away the division. It doesn't know the same thing about g.a: g is not a const object, a pointer to it has been passed into unknown code, so its value might have changed. So if you're the author of nobody_knows_what_this_does1 or nobody_knows_what_this_does2, and you're thinking of const_casting p and using it to modify its referand, then you can only do it if you somehow know that the referand is non-const. Which normally you don't, so normally you don't use const_cast.
I think you have the following options:
If you are sure the library is working as it should if it was using the const specifier, you could use const_cast<> to remove the const-ness of your objects when dealing with the library
Alternatively, you could make non-const copies of your const objects and pass those to the library, then update the changes to the non-const parts on your original objects
Search for another library that is const-correct
remove all const from your code (not recommended)
Another option is to copy your object into a modifiable temp and pitch it. This is probably the safest thing to do if you're in the circumstance where your class offers a copy constructor and it's not too expensive. This has been my preferred method when it's available, as I know it's 100% safe. Silly example:
int getInfoFromString(String& str); //what?? why isn't str const :(
So I do
String temp(str);
int stuffINeed = getInfoFromString(temp);
//happy
If the library's interface is not big, you can create a wrapper, where you would adjust your code to expected types, by either casting or making a copy of parameters, which are passed to library's functions.
But do not degrade your code in order to use the library.
Another suggestion: Are you familiar with the mutable keyword? If you use it correctly, it might actually accomplish exactly what you're trying to do, with exactly one word added to your code. This keyword can evoke religious opinion at the level of goto because it's probably used as a kludge for every hundred times that it's used because it really is the best design option. In your case, it's debatable which it is but I think it fits the spirit: your annoying library object is something that can be fake-modified without breaking the semantic const-ness of your methods, so go ahead.
class Outer {
mutable Inner inner;
public void foo() const {
inner.nonConstMethod(); //compiles because inner is mutable
}
};
I recently had an exchange with another C++ developer about the following use of const:
void Foo(const int bar);
He felt that using const in this way was good practice.
I argued that it does nothing for the caller of the function (since a copy of the argument was going to be passed, there is no additional guarantee of safety with regard to overwrite). In addition, doing this prevents the implementer of Foo from modifying their private copy of the argument. So, it both mandates and advertises an implementation detail.
Not the end of the world, but certainly not something to be recommended as good practice.
I'm curious as to what others think on this issue.
Edit:
OK, I didn't realize that const-ness of the arguments didn't factor into the signature of the function. So, it is possible to mark the arguments as const in the implementation (.cpp), and not in the header (.h) - and the compiler is fine with that. That being the case, I guess the policy should be the same for making local variables const.
One could make the argument that having different looking signatures in the header and source file would confuse others (as it would have confused me). While I try to follow the Principle of Least Astonishment with whatever I write, I guess it's reasonable to expect developers to recognize this as legal and useful.
Remember the if(NULL == p) pattern ?
There are a lot of people who will tell a "you must write code like this":
if(NULL == myPointer) { /* etc. */ }
instead of
if(myPointer == NULL) { /* etc. */ }
The rationale is that the first version will protect the coder from code typos like replacing "==" with "=" (because it is forbidden to assign a value to a constant value).
The following can then be considered an extension of this limited if(NULL == p) pattern:
Why const-ing params can be useful for the coder
No matter the type, "const" is a qualifier that I add to say to the compiler that "I don't expect the value to change, so send me a compiler error message should I lie".
For example, this kind of code will show when the compiler can help me:
void bar_const(const int & param) ;
void bar_non_const(int & param) ;
void foo(const int param)
{
const int value = getValue() ;
if(param == 25) { /* Etc. */ } // Ok
if(value == 25) { /* Etc. */ } // Ok
if(param = 25) { /* Etc. */ } // COMPILE ERROR
if(value = 25) { /* Etc. */ } // COMPILE ERROR
bar_const(param) ; // Ok
bar_const(value) ; // Ok
bar_non_const(param) ; // COMPILE ERROR
bar_non_const(value) ; // COMPILE ERROR
// Here, I expect to continue to use "param" and "value" with
// their original values, so having some random code or error
// change it would be a runtime error...
}
In those cases, which can happen either by code typo or some mistake in function call, will be caught by the compiler, which is a good thing.
Why it is not important for the user
It happens that:
void foo(const int param) ;
and:
void foo(int param) ;
have the same signature.
This is a good thing, because, if the function implementer decides a parameter is considered const inside the function, the user should not, and does not need to know it.
This explains why my functions declarations to the users omit the const:
void bar(int param, const char * p) ;
to keep the declaration as clear as possible, while my function definition adds it as much as possible:
void bar(const int param, const char * const p)
{
// etc.
}
to make my code as robust as possible.
Why in the real world, it could break
I was bitten by my pattern, though.
On some broken compiler that will remain anonymous (whose name starts with "Sol" and ends with "aris CC"), the two signatures above can be considered as different (depending on context), and thus, the runtime link will perhaps fail.
As the project was compiled on a Unix platforms too (Linux and Solaris), on those platforms, undefined symbols were left to be resolved at execution, which provoked a runtime error in the middle of the execution of the process.
So, because I had to support the said compiler, I ended polluting even my headers with consted prototypes.
But I still nevertheless consider this pattern of adding const in the function definition a good one.
Note: Sun Microsystems even had the balls to hide their broken mangling with an "it is evil pattern anyway so you should not use it" declaration. see http://docs.oracle.com/cd/E19059-01/stud.9/817-6698/Ch1.Intro.html#71468
One last note
It must be noted that Bjarne Stroustrup seems to be have been opposed to considering void foo(int) the same prototype as void foo(const int):
Not every feature accepted is in my opinion an improvement, though. For example, [...] the rule that void f(T) and void f(const T) denote the same function (proposed by Tom
Plum for C compatibility reasons) [have] the dubious distinction of having been voted into C++ “over my dead body”.
Source: Bjarne Stroustrup
Evolving a language in and for the real world: C++ 1991-2006, 5. Language Features: 1991-1998, p21.
http://www.stroustrup.com/hopl-almost-final.pdf
This is amusing to consider Herb Sutter offers the opposite viewpoint:
Guideline: Avoid const pass-by-value parameters in function declarations. Still make the parameter const in the same function's definition if it won't be modified.
Source: Herb Sutter
Exceptional C++, Item 43: Const-Correctness, p177-178.
This has been discussed many times, and mostly people end up having to agree to disagree. Personally, I agree that it's pointless, and the standard implicitly agrees -- a top-level const (or volatile) qualifier doesn't form part of the function's signature. In my opinion, wanting to use a top-level qualifier like this indicates (strongly) that the person may pay lip-service to separating interface from implementation, but doesn't really understand the distinction.
One other minor detail: it does apply to references just as well as pointers though...
It makes the compiler do part of the work of catching your bugs. If you shouldn't be modifying it, make it const, and if you forget, the compiler will yell at you.
If bar is marked const as above, then the person reading the code, knowing what was passed in, knows at all time exactly what bar contains. There's no need to look at any code beforehand to see if bar got changed at any point along the way. This makes reasoning about the code simpler and thus reduces the opportunity for bugs to creep in.
I vote "good practice" myself. Of course I'm also pretty much a convert to functional languages these days so....
Addressing the comment below, consider this source file:
// test.c++
bool testSomething()
{
return true;
}
int test1(int a)
{
if (testSomething())
{
a += 5;
}
return a;
}
int test2(const int a)
{
if (testSomething())
{
a += 5;
}
return a;
}
In test1 there is no way for me to know what the value being returned will be without reading the (potentially sizable and/or convoluted) body of the function and without tracking down the (potentially distant, sizable, convoluted and/or source-unavailable) body of the function testSomething. Further, the alteration of a may be the result of a horrific typo.
That same typo in test2 results in this at compile-time:
$ g++ test.c++
test.c++: In function ‘int test2(int)’:
test.c++:21: error: assignment of read-only parameter ‘a’
If it was a typo, it's been caught for me. If it isn't a typo, the following is a better choice of coding, IMO:
int test2(const int a)
{
int b = a;
if (testSomething())
{
b += 5;
}
return b;
}
Even a half-baked optimizer will generate identical code as in the test1 case, but you're signalling that care and attention will have to be paid.
Writing code for readability involves a whole lot more than just picking snazzy names.
I tend to be a bit of a const fiend so I personally like it. Mostly it's useful to point out to the reader of the code that the variable passed in wont be modified; in the same way that I try to mark every other variable that I create within a function body as const if it's not modified.
I also tend to keep the function signatures matching even though there's not much point in it. Partly it's because it doesn't do any harm and partly it's because Doxygen used to get a bit confused if the signatures were different.
I need to implement read-only access to a private member container. If I return a constant reference is it possible to const_cast it and obtain a full access to the member? What's the technique to be used?
Thanks.
Is it safe to return a const reference to a private member
Yes as long as the lifetime of the reference does not exceed the lifetime of the object which returned it. If you must expose the private member you do not want modified, this is a good way to do so. It's not foolproof but it's one of the better ways to do so in C++
Is it possible to use const_cast to actually mess around with member
Yes and there is nothing you can do to prevent this. There is no way to prevent someone from casting away const in C++ at any time. It's a limitation / feature of C++.
In general though, you should flag every use of const_cast as a bug unless it contains a sufficiently detailed comment as to why it's necessary.
Returning a const & is a sensible thing to do in many circumstances, particularly if the object being returned is large or cannot be copied.
Regarding the const_cast, remember the "private" access specifier in C++ is there as an aid to the programmer - it is not intended to be a security measure. If someone wants access to an object's private members, it can get them, no matter what you try to do to prevent it.
const int &ref = your_object.your_function();
*(int*)&ref = 1234;
Don't worry about users doing const_casts just to break your invariants. If they really want to break your code they can without you providing accessors to your internal attributes. By returning a constant reference, the common user will not mistakenly modify your data.
Encapsulation prevents mistakes, not espionage A malicious coder can break it anyway if they really care and know the environment (compiler). Const-ness is lost in the compilation process (in all compilers I know of). Once the compilation unit is converted into binary objects, those objects do not know about const-ness, and that can be exploited to take advantage.
// a.h
class A
{
public:
A( int a ) : data_( a ) {}
int get() const { return data_; }
private:
int data_;
};
// malicious.h
class A;
void change( A& a, int new_value );
// malicious.cpp
// does not include a.h, but redefines an almost exact copy of it
class A {
public:
A( int a ) : data_( a ) {}
int get() const { return data_; }
int data_; // private removed
};
void change( A& a, int new_value )
{
a.data_ = new_value;
}
// main.cpp
#include "a.h"
#include "malicious.h"
int main()
{
A a(0);
change( a, 10 );
std::cout << a.get() << std::endl; // 10
}
While the code above is incorrect (One definition rule is broken, there are two definitions for class A), the fact is that with most compilers the definition of A and malitious A are binary compatible. The code will compile and link, and the result is that external code has access to your private attributes.
Now that you know of it, don't do it. It will later be a maintenance pain in the ***. That has cost Microsoft quite a bit of money in providing backwards compatibility to software that used private parts of the API returned objects (new versions of the API that shared the same public interface but changed the internals would break some third party application code). With some broadly available software the provider (Microsoft in this case) will go through the pain of providing backwards compatibility, but with lesser known applications they won't and suddenly your previously running application will fail in all sort of ways.
I think it was Herb Sutter that once said that one should "Protect against Murphy, not against Machiavelli." That is, you should do everything possible to protect against the code being used incorrectly by accident, but there's nothing you can do about people abusing your code on purpose.
If someone really wants to break your code, they can, even if it's by #define private public before including your header (and thus creating an ODR violation, but I digress).
So yes, passing back a const ref is fine.
const_cast can be definitely used to obtain the full access to the member. I guess you can not stop people if they are hell bent on shooting themself on the foot. If the private member is not heavy, consider returning a copy of that variable.
Yes, so it's probably not what you want to do. On the other hand, if someone is going to the trouble of const casting your reference, it's possible they really know what they are doing.
It is possible to obtain a full access. But what for?
Don't forget to make accessor to be const correct
const MyType& getMyValue() const;
Also you can inject you private value in the callback.
void doJob( callback c )
{
c( myPrivateValue_ );
}
According to Scott Meyer's book, Effective C++ (see item #28), you should avoid it. Here is an excerpt from item #28:
This is why any function that returns a handle to an internal part of
the object is dangerous. It doesn’t matter whether the handle is a
pointer, a reference, or an iterator. It doesn’t matter whether it’s
qualified with const. It doesn’t matter whether the member function
returning the handle is itself const. All that matters is that a
handle is being returned, because once that’s being done, you run the
risk that the handle will outlive the object it refers to.