I want to compile the following line of code from http://code.google.com/p/enhsim:
enh::eout << enh::setw(26);
gcc gives the following error:
error: no match for 'operator<<' in 'enh::eout << enh::setw(26)'
But the EnhSimOutput class (of which enh::eout is an instance) does declare:
EnhSimOutput& operator<< (setw& p);
This problem goes away if I implement a version of the operation that accepts the object by value:
EnhSimOutput& operator<< (setw p);
or if I create the enh::setw object as a local, i.e.:
enh::setw wValue(26);
enh::eout << wValue;
My question is this: why does gcc not select the "by-reference" version of the operator to begin with?
The developers who wrote this code clearly made it compile, yet default gcc refuses to do it. Why is there a difference between an object declared separately as a local variable and a local created inline?
The value enh::setw(26); is an rvalue . Actually, temporaries like that are rvalues. Rvalues have special properties. One of them is that their address can't be taken (&enh::setw(26); is illegal), and they can't generally bind to references to non-const (some temporaries can bind to references to non-const, but these undergo special rules: Calling member functions on temporary objects and catching exception objects by reference to non-const. In the latter case, the temporary even is an lvalue).
There are two kind of expressions: lvalues that denote objects (that in turn may store an value) or functions, and rvalues which are meant to represent values read out of an object or represented by temporaries, numeral literals and enumerator constants. In C++03, to be able to pass such values to a function that accepts its value by-reference, there is a rule that they can be accepted by reference-to-const: setw const& p would accept it. That is, you would have to declare your operator like this:
EnhSimOutput& operator<< (setw const& p);
That's a bit unfortunate, because you can't disambiguate constant lvalues (objects you created on the stack using const enh::setw e(26); for example) and non-const or const rvalues (like enh::setw(26); which is a non-const temporary). Also, if you go by that, the parameter can't have called non-const member functions on it, because it's a reference-to-const. For that reason, C++1x, the next C++ version, introduce a new kind of reference, so-called rvalue-references which fixes that.
The Microsoft Visual C++ compiler binds rvalues to references to non-const, but gives out a warning when doing that (you have to use at least warning level 4 for it to show up). That's unfortunate, because problems rise up when porting to other compilers that are more strict in Standard compliance.
My guess is that EnhSimOutput& operator<< (setw& p); passes by non-const reference, but the value 26 is "const" in the sense that it cannot be modified. Try setting it to EnhSimOutput& operator<< (const setw& p);
or try
int nNumber = 26;
enh::eout << enh::setw(nNumber);
Related
I asked a related, tedious question before and now I discover something new.
#include <iostream>
#include <string>
using namespace std;
void hello (const string &s1) {
cout << "rocky" << endl;
}
void hello(string &s1) {
cout << "banana" << endl;
}
int main()
{
string s = "abc";
hello(const_cast<const string&>(s)); //how to explain this const_cast?
}
hello(const_cast<const string&>(s)); this works and match the const reference parameter function. So how's the conversion this time? Isn't it string to const string&?
Certainly I know that const reference can be initialized with non-const objects... But somehow I never take that as a conversion. I see it as an assignment. And I consider the type of reference and the type of referent as two very different stuff.
So, primary meaning for the cast is to pick necessary one from the list of overloaded hello() functions. Without the cast, we pick non-const version, otherwise it's const one.
Secondly, why the cast of the string reference, not just string type? This is due limitations of the const_cast itself. Let's try to compile that:
hello(const_cast<const string>(s)); // we removed the "&"
compiler message:
error: invalid use of const_cast with type ‘const string {aka const std::__cxx11::basic_string<char>}’,
which is not a pointer, reference, nor a pointer-to-data-member type
So, const_cast is not intended to create new instance, instead it works with indirection to given instance and just changes associated CV qualification (as it's free lunch in terms of code generation). So, we have to deal with a pointer or reference to conform that condition.
P.S. As far as I know, C++17 allows creation of temporary copies for the casting (aka Temporary materialization) so our non-ref attempt could have practical meaning. Same time, it's quite new concept and not so wide-spread.
Expressions, objects, variables - I know C++ can be a bit confusing to newcomers, especially when it comes to the subtle details.
So s here is a variable in main. While main runs (and that's the whole program, since it's main), there is an object that corresponds to the variable. And in main, the expression s refers to to that object. But there are many more expressions that refer to the same object. (s) is another expression that refers to the same object. So is *&s. Or *(&s).
s+"" is another expression that has the same value. But it's not the same object. Cf. integers i+0 or i*1.
References can be used to define variables which introduce new names for objects, names that can then be used in expressions. There are many places where it's convenient to be able to explicitly name something. It's just a new name, not a new object.
const_cast is another use for references. This however doesn't introduce a new name; it just forms a new expression with a const added to the type.
Now to your hello. This is an overloaded function. Overload resolution is done on the type of the expression used as an argument. So in hello(s1), s1 is the simple expression used for overload resolution, and its type is std::string. In hello(const_cast<std::string const&>(s1)), the expression is const_cast<std::string const&>(s1), and its type is obviously std::string const&.
Both expressions refer to the same object; they only differ in type. But that type difference is exactly what overload resolution needs.
You can only convert from const reference to lvalue reference explicitly by using const_cast as such conversion is not safe and must be explicit. On another side you can convert from lvalue or lvalue reference to const reference implicitly or explicitly, as such conversion is safe. So usually nobody cast to const reference explicitly as it is unnecessary verbose and does not make sense. In your case it is converted explicitly to select certain overloaded function, because compiler would not convert it implicitly, as it can find overload with lvalue reference, but your example is rather artificial, as it is difficult to imagine why somebody would have such overload.
While there are zillions of sources on clarifying the concept of references in C++, I'm trying to explain the concept of reference to someone who is familiar with pointers. In other words, I'm wondering whether the following semantic expression is ALWAYS true?
TYPE& == *(TYPE const *)
The expression
TYPE& == *(TYPE const *)
looks a bit of domain error as TYPE& is a type while *(TYPE const*) looks like an expression applied to a type. At the very least, the right hand side should be const pointer rather than a pointer to const, i.e.:
A TYPE& behaves like an auto-dereferenced immutable pointer, something like *(TYPE* const) with the implicit constraint that the pointer cannot be null.
The compiler does recognize references and in some cases, namely when binding temporaries to a reference to a const object (T const&) at function scope: the life-time of the temporary gets expanded until the reference goes out of scope! For example:
{
std::string const& s = std::string("longer lived");
// the original temporary created above still lives
} // <-- ... and gets destroyed when s goes out of scope here
Another major difference between pointers and references are semantics when it comes to operator overloading: pointers are consider built-in types and operators only involving built-in types cannot be overloaded. A reference of type T& behaves like a T object, i.e., overloaded operators for T& are considered. That is, while the a T& is identical to using a T* const from a representation point of view, the compiler understands the difference and treats the entities differently on a semantic level.
Yes, if you disassemble C++ code in Visual Studio, reference is nothing but const pointer. So both are almost equivalent.
But be aware, you cannot assign NULL (0/nullptr) to reference.
Probably the best way to explain references is to use Stroustroup's example showing how they allow creating functions that replace macros, something that would not be possible without references.
The stated possible type equivalence TYPE& == *(TYPE const *) does not make literal sense since the right hand side isn't a type, and since it's about a pointer to const instead of a const pointer.
However, considering the thing in an associative sense, one can imagine a rewrite rule where a reference declaration
T& r = o;
is rewritten as
T* const __p = &o;
and where every use of r is then rewritten as
(*__p)
Except for handling of the case where o is an rvalue expression it explains most and perhaps all practical properties of references.
However, as the relevant FAQ item “How can you reseat a reference to make it refer to a different object?” states,
” please don't confuse references with pointers; they're very different from the programmer's standpoint
One of the ways it differs, is that you cannot take the address of a reference,
but you can take the address of a pointer. Since you can take the address of a
pointer, it must have storage. However, references do not have to have storage
(they are defined in the standard as aliases), and as often the compiler can,
they will in fact not have storage.
I'm currently writing a double linked list using dynamic memory in C++ for one of my classes. I've already got the code written, I just had a question.
Our professor required us to write both an
int& operator[](int position)
AND an
int operator[](int position) const
function.
What was the point in doing two functions for the same operator? I'm sure there's some kind of logic behind it, haha. Is it just so I can do a = arr[i] and also do arr[i] = a?
If you have a const list object, you should only be able to read values from it. If you have a modifiable one, you should be able to both read and write values. The first is done with the const version, which will be called for a const object.
When your object is const, you can only use the const version of the operator, which by virtue of being const doesn't allow modification of your object or returning non-cons pointers/references to internal members. So when your object is non-const you need a non-const operator that allows modifications so you can write foo[i]=n
1) The const variant is for reading, e.g. when you assign a value to a variable. The compiler will give you an error when trying to modify the list value at the specified index. Example for const is a = arr[i] as you wrote.
2) The non-const variant is usually used when you actually set the value at the certain index of the list. Although you could use this variant for getting a value as well. However, then the compiler would not raise an error when your intention is to just read and your code would accidentally write. That could lead to subtle bugs which you can avoid by using const for such cases. Example for non-const is arr[i] = a as you wrote.
If you have both versions present, the non-const version version will be called for reading when you execute the indexing on a non-const object.
Is it just so I can do a = arr[i] and also do arr[i] = a?
Yes, that's what it's for.
if you have a const or a non-const list then you can perform the a = arr[i] assignment;
the version of the operator that returns an int& is so that you can perform arr[i] = a, which of course requires a non-const list.
Its just if you have a const variable of your object, lets call it A const a; then you are only allowed to call const functions, like your const overload of operator [] (...) const, which only provides reading. You are not allowed to call the non const operator [] (...) in this case.
Where you have a doubly-linked list object that is defined with the const qualifier (commonly called "a const object") or referred to via a pointer-to-const or a reference-to-const, you want to be enable reading but not writing. The const-qualified operator does that.
Where you have an object that is defined without the const qualifier, or referred to via a pointer-to-non-const or a reference-to-non-const, you want to enable both reading and writing. The non-const-qualified operator does that.
So, the reason you bother writing two overloads is to implement both behaviours.
If you only wanted reading, regardless of constness, then you would only write the const version because const-qualified member functions can be used to interact with both cases, whereas non-const-qualified member functions can only be used on the names of non-const-qualified objects (or via a pointer-to-non-const or a reference-to-non-const).
If you only wanted operator[] to apply to non-const objects then you would only write the non-const-qualified version. This might seem strange, since you don't expect operator[] to need the object to be modifiable, but as it happens this is exactly what std::map does with operator[].
Say the object is
class A {
public : void Silly(){
this = 0x12341234;
}
I know I will get compiler error ' "this" is not a lvalue.' But then it is not a temporary either. So what is the hypothetical declaration of "this" ?
Compiler : GCC 4.2 compiler on mac.
For some class X, this has the type X* this;, but you're not allowed to assign to it, so even though it doesn't actually have the type X *const this, it acts almost like it was as far as preventing assignment goes. Officially, it's a prvalue, which is the same category as something like an integer literal, so trying to assign to it is roughly equivalent to trying to assign a different value to 'a' or 10.
Note that in early C++, this was an lvalue -- assigning to this was allowed -- you did that to handle the memory allocation for an object, vaguely similar to overloading new and delete for the class (which wasn't supported yet at that time).
It is impossible to provide a "declaration" for this. There's no way to "declare" an rvalue in C++. And this is an rvalue, as you already know.
Lvalueness and rvalueness are the properties of expressions that produce these values, not the properties of declarations or objects. In that regard, one can even argue that it impossible to declare an lvalue either. You declare an object. Lvalue is what is produced when you use the name of that object as an expression. In that sense both "to declare an rvalue" and "to declare an lvalue" are oxymoron expressions.
Your question also seems to suggest that the properties of "being an lvalue" and "being a temporary" are somehow complementary, i.e. everything is supposedly an lvalue or a temporary. In reality, the property of "being a temporary" has no business being here. All expressions are either lvalues or rvalues. And this happens to be an rvalue.
Temporaries, on the other hand, can be perceived as rvalues or as lvalues, depending on how you access the temporary.
P.S. Note, BTW, that in C++ (as opposed to C) ordinary functions are lvalues.
For one thing, this is not a variable - it's a keyword. When used as a rvalue, its type is A * or A const *. In modern C++, assigning to this is prohibited. You cannot take the address of this, either. In other words, it's not a valid lvalue.
To answer the second part, "why is this not an lvalue", I'm speculating as to the committee's actual motivation, but advantages include:
assigning to this doesn't make much logical sense, so there's no particular need for it to appear on the left-hand-side of assignments. Making it an rvalue emphasises that this doesn't make much sense by forbidding it, and means that the standard doesn't have to define what happens if you do it.
making it an rvalue prevents you taking a pointer to it, which in turn relieves the implementation of any need to furnish it with an address, just like a register-modified automatic variable. It could for example devote a register in non-static member functions to storing this. If you take a const reference, then unless the use permits cunning optimization it needs to be copied somewhere that has an address, but at least it needn't be the same address if you do it twice in quick succession, as it would need to be if this were a declared variable.
You get a compiler error because this is a const pointer to the instance of the class of the same type as that class. You can't assign to it although you can use it to change other class members in non-const qualified methods, call methods, and operators. Also note because it's an instance that static methods do not have a this pointer.
Hypothetical:
class Whatever
{
// your error because this is Whatever* const this;
void DoWhatever(const Whatever& obj) { this = &obj; }
// this is ok
void DoWhatever(const Whatever& obj) { *this = obj; }
// error because this is now: const Whatever* const this;
void DoWhatever(const Whatever& obj) const { *this = obj; }
// error because this doesn't exist in this scope
static void DoWhatever(const Whatever& obj) { *this = obj; }
};
Which is better:
bool MyClass::someQuery() const;
const bool MyClass::someQuery() const;
I've been using 'const bool' since I'm sure I remember hearing it's "what the ints do" (for e.g. comparison operators) but I can't find evidence of that anywhere, mostly due to it being difficult to Google and Intellisense not helping out any ;) Can anyone confirm that?
To me returning const values (this isn't just about bools) makes more sense; it'll prevent temporaries being modified, which is almost always going to be a programmer mistake. I just want something to back that up so I can extol returning const values to my colleagues :)
This is the case when const adds no value but inflates the code and makes the reader think more. What's the point of this const? The caller can copy the value into some non-const variable and do whatever he wants with it anyway.
So you know it's right, you're just after the Voice of Authority?
Preventing accidental modification of temporaries is very valuable. In general, you should declare as many things as you possibly can const, it protects you from a variety of accidents and gives the optimiser useful hints.
D'you have a copy of Scott Meyers' "Effective C++" around? Point them at Item 3 (page 18 in the third edition) ;)
It gives the example of
class Rational {...};
const Rational operator* (const Rational& lhs, const Rational& rhs );
if( (a * b) = c ) // declaring operator *'s return value const causes error to be caught by compiler
Note that if((a*b) = c) won't compile for built-in types anyway, so it is very relevant here whether we're talking built-in types (your question asks for bool) or user-defined types.
For built-in types it makes no sense at all, so it shouldn't be used. And for user-defined types, I'm in jalf's camp: What if the caller wants to modify the returned object?
I'm not convinced that if((a*b) = c) is such a good argument for returning const user-defined types, since I can't remember the last time I've seen a compiler not warn about this.
To be a little more specific, only "objects" can be const. The C++ standard's definition of "object" includes everything an lvalue refers to ("has a name") and class-type temporaries. A boolean return value is an rvalue of a non-class type which is why a standards-compliant compiler will just ignore "const" in this case. As others said already, it's useless in this context.
When you returning a refernce to a member variable it makes sense to make it const. Here you are returning a copy, hence there is no need of const.
The const modifier is only used for return types that are returned by reference (either as reference const SomeObject& or via a pointer const SomeObject*), so the caller won't be able to modify the object via the reference/pointer. Primitive types are returned by value, which means that the caller receives a copy of the the object, not the object itself.
Therefore, const is not really appropriate for returned value types. Since the copy is outside of the control of the called function, the called function should not dictate to the caller that it cannot be changed.
This is an ancient post, but I think it's worth mentioning there is a potential corner case here since C++11. While, as stated by others, it will make no difference whether you use const bool or bool as return type in most cases, if you are using C++11 decltype and associates, e.g. result_of, you could declare a variable with the same type as the returning value of some function, and so the const would actually have an effect in this case.
It completely doesn't matter. Therefore, the consensus is to return just bool.
The reason that it doesn't matter is that you can't call non-const member functions anyway; bool is not a class or struct.
As bool is going to be copied, it's the same, to put const or not. Plus you'll may have some compil problems.
const return type
SUMMARY:
The value of a return type that is
declared const cannot be changed. This
is especially usefull when giving a
reference to a class’s internals, but
can also prevent rarer errors.
const bool func();
bool f = func();
0 errors, 0 warnings. What have you accomplished other than unnecessary code inflation?