Why does C++ need the scope resolution operator? - c++

(I know what the scope resolution operator does, and how and when to use it.)
Why does C++ have the :: operator, instead of using the . operator for this purpose? Java doesn't have a separate operator, and works fine. Is there some difference between C++ and Java that means C++ requires a separate operator in order to be parsable?
My only guess is that :: is needed for precedence reasons, but I can't think why it needs to have higher precedence than, say, .. The only situation I can think it would is so that something like
a.b::c;
would be parsed as
a.(b::c);
, but I can't think of any situation in which syntax like this would be legal anyway.
Maybe it's just a case of "they do different things, so they might as well look different". But that doesn't explain why :: has higher precedence than ..

Because someone in the C++ standards committee thought that it was a good idea to allow this code to work:
struct foo
{
int blah;
};
struct thingy
{
int data;
};
struct bar : public foo
{
thingy foo;
};
int main()
{
bar test;
test.foo.data = 5;
test.foo::blah = 10;
return 0;
}
Basically, it allows a member variable and a derived class type to have the same name. I have no idea what someone was smoking when they thought that this was important. But there it is.
When the compiler sees ., it knows that the thing to the left must be an object. When it sees ::, it must be a typename or namespace (or nothing, indicating the global namespace). That's how it resolves this ambiguity.

Why C++ doesn't use . where it uses ::, is because this is how the language is defined. One plausible reason could be, to refer to the global namespace using the syntax ::a as shown below:
int a = 10;
namespace M
{
int a = 20;
namespace N
{
int a = 30;
void f()
{
int x = a; //a refers to the name inside N, same as M::N::a
int y = M::a; //M::a refers to the name inside M
int z = ::a; //::a refers to the name in the global namespace
std::cout<< x <<","<< y <<","<< z <<std::endl; //30,20,10
}
}
}
Online Demo
I don't know how Java solves this. I don't even know if in Java there is global namespace. In C#, you refer to global name using the syntax global::a, which means even C# has :: operator.
but I can't think of any situation in which syntax like this would be legal anyway.
Who said syntax like a.b::c is not legal?
Consider these classes:
struct A
{
void f() { std::cout << "A::f()" << std::endl; }
};
struct B : A
{
void f(int) { std::cout << "B::f(int)" << std::endl; }
};
Now see this (ideone):
B b;
b.f(10); //ok
b.f(); //error - as the function is hidden
b.f() cannot be called like that, as the function is hidden, and the GCC gives this error message:
error: no matching function for call to ‘B::f()’
In order to call b.f() (or rather A::f()), you need scope resolution operator:
b.A::f(); //ok - explicitly selecting the hidden function using scope resolution
Demo at ideone

Why does C++ have the :: operator, instead of using the . operator for this purpose?
The reason is given by Stroustrup himself:
In C with Classes, a dot was used to express membership of a class as well as expressing selection of a member of a particular object.
This had been the cause of some minor confusion and could also be used to construct ambiguous examples. To alleviate this, :: was introduced to mean membership of class and . was retained exclusively for membership of object
(Bjarne Stroustrup A History of C++: 1979−1991 page 21 - § 3.3.1)
Moreover it's true that
they do different things, so they might as well look different
indeed
In N::m neither N nor m are expressions with values; N and m are names known to the compiler and :: performs a (compile time) scope resolution rather than an expression evaluation. One could imagine allowing overloading of x::y where x is an object rather than a namespace or a class, but that would - contrary to first appearances - involve introducing new syntax (to allow expr::expr). It is not obvious what benefits such a complication would bring.
Operator . (dot) could in principle be overloaded using the same technique as used for ->.
(Bjarne Stroustrup's C++ Style and Technique FAQ)

Unlike Java, C++ has multiple inheritance. Here is one example where scope resolution of the kind you're talking about becomes important:
#include <iostream>
using namespace std;
struct a
{
int x;
};
struct b
{
int x;
};
struct c : public a, public b
{
::a a;
::b b;
};
int main() {
c v;
v.a::x = 5;
v.a.x = 55;
v.b::x = 6;
v.b.x = 66;
cout << v.a::x << " " << v.b::x << endl;
cout << v.a.x << " " << v.b.x << endl;
return 0;
}

Just to answer the final bit of the question about operator precedence:
class A {
public:
char A;
};
class B : public A {
public:
double A;
};
int main(int c, char** v)
{
B myB;
myB.A = 7.89;
myB.A::A = 'a';
// On the line above a hypothetical myB.A.A
// syntax would parse as (myB.A).A and since
// (myB.A) is of type double you get (double).A in the
// next step. Of course the '.' operator has no
// meaning for doubles so it causes a syntax error.
// For this reason a different operator that binds
// more strongly than '.' is needed.
return 0;
}

I always assumed C++ dot/:: usage was a style choice, to make code easier to read. As the OP writes "they do different things, so should look different."
Coming from C++, long ago, to C#, I found using only dots confusing. I was used to seeing A::doStuff(); B.doStuff();, and knowing the first is a regular function, in a namespace, and the second is a member function on instance B.
C++ is maybe my fifth language, after Basic, assembly, Pascal and Fortran, so I don't think it's first language syndrome, and I'm more a C# programmer now. But, IMHO, if you've used both, C++-style double-colon for namespaces reads better. I feel like Java/C# chose dots for both to (successfully) ease the front of the learning curve.

Scope resolution operator(::) is used to define a function outside a class or when we want to use a global variable but also has a local variable with same name.

Related

What is the point of the scope resolution operators?

A question dawned on me lately: Why bother having the scope resolution operator (::) when the usage of the dot operator (.) doesn't clash with the former?
Like,
namespace my_module
{
const int insane_constant = 69;
int some_threshold = 100;
}
In order to access some_threshold, one would write my_module::some_threshold. But the thing is the left hand side of :: must be a namespace or a class, as far as I know, while that of the . can never be a namespace or a class. Moreover, the order of :: is higher than ., which is really pointless in my opinion. Why make 2 distinct operators, both of which cannot be overloaded, with use cases can be covered with just one? I'm having a hard time finding any satisfying answer, so any clue on this matter is much appriciated.
Consider the following code:
#include <iostream>
namespace my_module
{
const int insane_constant = 69;
}
class C{
public:
int insane_constant; // actually not constant, but for the example's sake
};
int main(){
C my_module;
my_module.insane_constant = my_module::insane_constant;
std::cout << my_module.insane_constant;
}
How would you distinguish my_module. from my_module:: here?
You can't replace one with the other.
Example:
namespace A
{
int x = 0;
struct X { int x = 1; } A;
void f()
{
std::cout << A.x
<< A::x
<< std::endl;
}
}
int main()
{
A::f();
}
prints "10".
Both operators have completely different purposes.
In particular, :: is for referring to a member of a scope while operator. is for referring to a member of an object.
That is, operator:: works on scope while operator. works on objects.
For instance, a classname::membername refers to the member of a class which has a class scope associated with it. On the other hand, object.membername refers to the member of the object object.
Note that not all scopes can be used with operator::. For example, we can refer to a namespace scope's member, class scopes' member(like a static member etc), enumeration' member etc using operator::.
The other answers showcase situations where :: and . do different things because they act on different entities (scopes vs objects). I'd like to add a bit of motivation behind this choice in the language by comparing it with the situation in C#. Disclaimer: I don't actually use C#, but these points seem obvious when looking into it.
In C#, the "namespace operator" is a dot ., just like the member access operator. However, you cannot have truly global variables: you need a class to put them in. In fact, you cannot even declare a class without a namespace, though this is unrelated to your question.
In C#, there is no possible ambiguity when using the dot between scope and object. Nested namespaces, classes within namespaces, class static variables, enumerators, and so on, are all accessed with a dot.
In C++, that's obviously not the case, and the language took the route of distinguishing between scopes and objects by having two distinct operators.
In plain C, there is no scope resolution, so there is no need for a :: operator. Other languages that make the distinction are Ruby and, apparently, PHP. Among languages that do not make the distinction, you can find for example Python, Go and Java. That last one does have a :: operator, but it's not for scope resolution, it's for forming method references.
In short, C++ has complex scope mechanisms because that's how the language was designed. As a result, it requires two different operators to distinguish scope access and object access.

Understanding scope with inheritance in C++

I'm testing my understanding of inheritance in C++ and was reading through some example code. Based on the program output, it seems to me that the double add() and int add() functions have different scope, and instead of calling the double add() function with argument 10.5, there is an implicit type conversion from double to int (which is always truncated) and the function int add() is called instead. The type conversion would explain why the output is 11 11.
My questions are as follows:
What is the scope of inherited functions that are overloaded?
When, if ever, is a type conversion from double to int invalid (i.e. would instead result in a compile-time error)?
Where can I read more about the nuances of namespaces/scope with inheritance in C++?
#include <iostream>
using namespace std;
class One {
public:
double add(double x) { return x + 0.1; }
};
class Two : public One {
public:
int add(int x) { return x + 1; }
};
int main(int argc, char *argv[]) {
Two obj;
cout << obj.add(10) << " " << obj.add(10.5) << endl;
return 0;
}
The declaration of add as int add(int x) { return x + 1; } hides any other definitions of add from outer scopes, this is the same behaviour as shadowing of variables in nested blocks in a function.
Name lookup always finds a name in a scope before going on to potential overload resolution amongst multiple occurrences of that name in the same scope; obj.add(10.5) finds Two::add() and so does not go on to check outer scopes.
You can redeclare the functions from outer scopes in Two with using One::add;
On the conversion topic; a double argument always matches an int parameter. It can be invalid if the double is out of range for int but that is runtime undefined behaviour (no diagnostic required).
This topic is covered in C++ FAQ , you could also check the Name Lookup article on cppreference.
Overloading does not work with inheritance in C++:
Overloading doesn’t work for derived class in C++ programming
language. There is no overload resolution between Base and Derived.
The compiler looks into the scope of Derived, finds the single
function “double f(double)” and calls it. It never disturbs with the
(enclosing) scope of Base. In C++, there is no overloading across
scopes – derived class scopes are not an exception to this general
rule
The example they used had double f(double) in the derived class.
https://www.geeksforgeeks.org/does-overloading-work-with-inheritance/
To fix this, the class would have to be redesigned. I can't give any specific feedback as to how to change it as the class is very generic.
In addition to the answers above, I would like to add that you can avoid this issue of overloading by creating a template for One::add() which will allow it to accept both integers and doubles, and then let class Two inherite it.
#include <iostream>
using namespace std;
class One {
public:
template <typename T> //Template allows us to create a function template whose functionality can be adapted to more than one type or class without repeating the entire code for each type.
double add(T x)
{
if (floor(x) == x) //Check if x is integer
return x + 1;
else
{
return x + 0.1;
}
}
};
class Two : public One {
public:
//No need for overloading add() here because in Class One, add() function will accept integers and doubles
};
int main(int argc, char* argv[]) {
Two obj;
cout << obj.add(10) << " " << obj.add(10.5) << endl;
return 0;
}

Multiple inheritance with the same variable name in the classes

I accidentally run into the problem having member variables with the same name in classes used in multiple inheritance. My basic idea was that the member variables are simple "merged", i.e. a multiple declaration happens. The compiler did not tell me even a warning, see the MWE below.
I understand that it is a bad idea to have variables with the same name, so I think it is at least ambiguous to refer to them in the way I do; so I expected at least a warning or maybe an error.
1) Why the compiler does not write out at least a warning?
2) How handling of those variables is solved internally? (I guess aliases like HW::I and Other::I are used, but how they relate to SW1::I and SW2::I?)
#include <iostream>
struct Other { int I;};
struct HW { int I;};
struct SW1 : Other, HW { int I;};
struct SW2 : HW, Other { int I;};
struct D : SW1 { };
struct E : SW2 { };
int main()
{
E* e = new E;
D* d = new D;
e->I = 3;
SW1* pc1 = dynamic_cast<SW1*>(d);
pc1->I = 2;
std::cerr << d->I;
std::cerr << e->I;
SW2* pc2 = dynamic_cast<SW2*>(e);
pc2->I = 1;
std::cerr << d->I;
std::cerr << e->I;
}
Why the compiler does not write out at least a warning?
Because you didn't write anything wrong, dangerous or ambiguous. You or I may be confused, but the compiler has a specific set of lookup rules to handle it.
When you write a class member access expression like e->I, the compiler doesn't just look up the name I, it looks up the sub-object that contains the member named this way, along with the member. It also starts with the most derived object type, and looks "up" at base class sub-object until it finds something (this is also how member name hiding in C++ works, in a nutshell).
So for e->I, it looks for I in E. That search finds nothing, so it goes into the base class subject. It find SW2::I, a name that refers to a unique member defined in SW2. So it stops.
If there was no SW2::I, it will continue looking and find both Other::I and HW::I. Now the same name is found in two different base class sub-object, and we get an ambiguity. Not a warning of ambiguity, but flat out making the expression e->I ambiguous, which is an error.
The compiler is correct not to diagnose any problems with your code. The code, as you've constructed it is not ambiguous. Essentially, a name is ambiguous if it is an equally good match for more than one variable (or class member in your case).
When evaluating e->I, the first candidate found is the I that is a member (via inheritance) of class SW2. The members of I that SW2 inherits from its base classes are not as good a match as the member defined directly by Sw2.
Similarly, pc1->I is unambiguously the member of SW1, d->I is the same, and pc2->I is unambiguously the member of the base class SW2.
Ambiguity would occur in evaluating e->I if SW2 did not have its own member named I (i.e. struct SW2: HW, Other {};( . In that case, when evaluating e->I, the name resolution looks in SW2 for a member named I, and doesn't find it. Resolving the name then considers the two base classes, HW and Other, which both have a member named I. They are equally good matches, so the expression e->I is ambiguous - and the compiler will issue a diagnostic i.e. an error (not just a warning). In that case, it is possible for the programmer to explicitly resolve the ambiguity using the scope (::) operator. For example, e->HW::I or e->Other::I which fully qualifies the name.
You are right that such multiple usage of a name within a class hierarchy is a bad idea. Both because it can be difficult to correctly resolve the ambiguity in a way that makes sense to a compiler, and because mere mortals will often have trouble following the logic.
The variables are not merged, you simply get all 3 of them at the same time. You need to cast the pointer to the right type to access the variable you want.
#include <iostream>
struct Other { int I; };
struct HW { int I; };
struct SW1 : public Other, public HW { int I; };
struct D : public SW1 { };
int main() {
D* d = new D;
d->I = 1;
SW1* pc1 = dynamic_cast<SW1*>(d);
pc1->I = 2;
static_cast<Other*>(pc1)->I = 3;
static_cast<HW*>(pc1)->I = 4;
std::cerr << d->I;
std::cerr << static_cast<Other*>(d)->I;
std::cerr << static_cast<HW*>(d)->I;
}
Prints:
234
I.e. the same object d contains 3 different versions of I, depending on how you view it.

When to use "::" and when to use "." [duplicate]

This question already has answers here:
When do I use a dot, arrow, or double colon to refer to members of a class in C++?
(4 answers)
Closed 8 years ago.
Apologies for a question that I assume is extremely basic.
I am having trouble finding out online the difference between the operator :: and . in C++
I have a few years experience with C# and Java, and am familiar with the concept of using . operator for member access.
Could anyone explain when these would be used and what the difference is?
Thanks for your time
The difference is the first is the scope resolution operator and the second is a member access syntax.
So, :: (scope resolution) can be used to access something further in a namespace like a nested class, or to access a static function. The . period operator will simply access any visible member of the class instance you're using it on.
Some examples:
class A {
public:
class B { };
static void foo() {}
void bar() {}
};
//Create instance of nested class B.
A::B myB;
//Call normal function on instance of A.
A a;
a.bar();
//Call the static function on the class (rather than on an instance of the class).
A::foo();
Note that a static function or data member is one that belongs to the class itself, whether or not you have created any instances of that class. So, if I had a static variable in my class, and crated a thousand instances of that class, there's only 1 instance of that static variable still. There would be 1000 instances of any other member that wasn't static though, one per instance of the class.
One more interesting option for when you come to it :) You'll also see:
//Create a pointer to a dynamically allocated A.
A* a = new A();
//Invoke/call bar through the pointer.
a->bar();
//Free the memory!!!
delete a;
Dynamic memory can be a little more confusing if you haven't learned it yet, so I won't go into details. Just wanted you to know that you can access members with { :: or . or -> } :)
in C++ :: is the scope resolution operator. It is used to distinguish namespaces, and static methods, basically any case you don't have an object. Where . is used to access things inside an object.
C# uses the . operator for both of them.
namespace Foo
{
public class Bar
{
public void Method()
{
}
public static void Instance()
{
}
}
}
in C# you would write code like this:
var blah = new Foo.Bar();
blah.Method();
but the equivalent C++ code would look more like this:
Foo::Bar blah;
blah.Method();
But note that the static method would also be accessed using the scope resolution operator, because you're not referencing an object.
Foo::Bar::Instance();
Where again, the C# code would only use the dot operator
Foo.Bar.Instance();
:: is for namespaces and static member access. C# uses the dot-operator for namespaces instead.
. is for non-static member access.
Not an exhaustive delineation, but it's the relevant bits that may confuse you in light of C# and Java.
For further information, see
IBM - Scope Resolution Operator
IBM - Dot Operator
:: is the scope resolution operator, so when you are resolving a scope, such as a namespace or class, you use that. For member access, you have .
The scope operator :: may be hard to understand if you don't understand namespaces or classes. A namespace is like a container for the names of various things in your code. They're generally used to disambiguate names that are common across libraries. Say both namespaces std and example have the function foobar(). So the compiler knows which function you want to use, you prepend it as either std::foobar() or example::foobar().
The :: operator can also be used when telling the compiler you want to define a function declared in a class or structure. For instance:
class foobar()
{
public:
void hello();
int number; //assume there is a constructor that sets this to 5
}
void foobar::hello()
{
cout << "Hello, world!" << endl;
}
The . operator is used when you wish to use a member of a class or structure. For instance:
foobar foo;
foo.hello();
cout << foo.number << endl;
Assuming the class is completed by writing a constructor, the output of this would be expected to be:
Hello, world!
5
You use the . operator the same in java, when accessing members of a class once its created in the program.
the :: is used in number of cases:
When you define a method in the .h/.cpp of a certain class, write
class::methodName()
either for prototyping it, or implementing it.
Also, if you don't explicitly state what namespace you use, you'd have to to use it
std::cout << "This is the output";
instead of just using cout << "This is the output;
Maybe there are more, but i don't remember right now, my C++ is a bit rusty.
In C++, :: is for identifying scope. This can mean namespace scope or class scope.
Eg.
int x;
namespace N {
int x;
struct foo {
static double x;
double y;
};
struct bar: public foo {
double y;
};
}
int main()
{
int x; // we have a local, hiding the global name
x = ::x; // explicitly identify the x in global scope
x += N::x; // explicitly identify the x in namespace N
N::foo::x = x; // set the static member of foo to our local integer
N::foo f;
f.y = f.x; // the static member is implicitly scoped by the object
f.y += N::foo::x; // or explicitly scoped
N::bar b;
assert(b.x == N::foo::x); // this static member is inherited
b.y = b.x; // we get N::bar::y by default
b.N::foo::y = b.y; // explicitly request the hidden inherited one
}
// we need to define the storage for that static somewhere too ...
int N::foo::x (0.0);

Hidden Features of C++? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
No C++ love when it comes to the "hidden features of" line of questions? Figured I would throw it out there. What are some of the hidden features of C++?
Most C++ programmers are familiar with the ternary operator:
x = (y < 0) ? 10 : 20;
However, they don't realize that it can be used as an lvalue:
(a == 0 ? a : b) = 1;
which is shorthand for
if (a == 0)
a = 1;
else
b = 1;
Use with caution :-)
You can put URIs into C++ source without error. For example:
void foo() {
http://stackoverflow.com/
int bar = 4;
...
}
Pointer arithmetics.
C++ programmers prefer to avoid pointers because of the bugs that can be introduced.
The coolest C++ I've ever seen though? Analog literals.
I agree with most posts there: C++ is a multi-paradigm language, so the "hidden" features you'll find (other than "undefined behaviours" that you should avoid at all cost) are clever uses of facilities.
Most of those facilities are not build-in features of the language, but library-based ones.
The most important is the RAII, often ignored for years by C++ developers coming from the C world. Operator overloading is often a misunderstood feature that enable both array-like behaviour (subscript operator), pointer like operations (smart pointers) and build-in-like operations (multiplying matrices.
The use of exception is often difficult, but with some work, can produce really robust code through exception safety specifications (including code that won't fail, or that will have a commit-like features that is that will succeed, or revert back to its original state).
The most famous of "hidden" feature of C++ is template metaprogramming, as it enables you to have your program partially (or totally) executed at compile-time instead of runtime. This is difficult, though, and you must have a solid grasp on templates before trying it.
Other make uses of the multiple paradigm to produce "ways of programming" outside of C++'s ancestor, that is, C.
By using functors, you can simulate functions, with the additional type-safety and being stateful. Using the command pattern, you can delay code execution. Most other design patterns can be easily and efficiently implemented in C++ to produce alternative coding styles not supposed to be inside the list of "official C++ paradigms".
By using templates, you can produce code that will work on most types, including not the one you thought at first. You can increase type safety,too (like an automated typesafe malloc/realloc/free). C++ object features are really powerful (and thus, dangerous if used carelessly), but even the dynamic polymorphism have its static version in C++: the CRTP.
I have found that most "Effective C++"-type books from Scott Meyers or "Exceptional C++"-type books from Herb Sutter to be both easy to read, and quite treasures of info on known and less known features of C++.
Among my preferred is one that should make the hair of any Java programmer rise from horror: In C++, the most object-oriented way to add a feature to an object is through a non-member non-friend function, instead of a member-function (i.e. class method), because:
In C++, a class' interface is both its member-functions and the non-member functions in the same namespace
non-friend non-member functions have no privileged access to the class internal. As such, using a member function over a non-member non-friend one will weaken the class' encapsulation.
This never fails to surprise even experienced developers.
(Source: Among others, Herb Sutter's online Guru of the Week #84: http://www.gotw.ca/gotw/084.htm )
One language feature that I consider to be somewhat hidden, because I had never heard about it throughout my entire time in school, is the namespace alias. It wasn't brought to my attention until I ran into examples of it in the boost documentation. Of course, now that I know about it you can find it in any standard C++ reference.
namespace fs = boost::filesystem;
fs::path myPath( strPath, fs::native );
Not only can variables be declared in the init part of a for loop, but also classes and functions.
for(struct { int a; float b; } loop = { 1, 2 }; ...; ...) {
...
}
That allows for multiple variables of differing types.
The array operator is associative.
A[8] is a synonym for *(A + 8). Since addition is associative, that can be rewritten as *(8 + A), which is a synonym for..... 8[A]
You didn't say useful... :-)
One thing that's little known is that unions can be templates too:
template<typename From, typename To>
union union_cast {
From from;
To to;
union_cast(From from)
:from(from) { }
To getTo() const { return to; }
};
And they can have constructors and member functions too. Just nothing that has to do with inheritance (including virtual functions).
C++ is a standard, there shouldn't be any hidden features...
C++ is a multi-paradigm language, you can bet your last money on there being hidden features. One example out of many: template metaprogramming. Nobody in the standards committee intended there to be a Turing-complete sublanguage that gets executed at compile-time.
Another hidden feature that doesn't work in C is the functionality of the unary + operator. You can use it to promote and decay all sorts of things
Converting an Enumeration to an integer
+AnEnumeratorValue
And your enumerator value that previously had its enumeration type now has the perfect integer type that can fit its value. Manually, you would hardly know that type! This is needed for example when you want to implement an overloaded operator for your enumeration.
Get the value out of a variable
You have to use a class that uses an in-class static initializer without an out of class definition, but sometimes it fails to link? The operator may help to create a temporary without making assumptins or dependencies on its type
struct Foo {
static int const value = 42;
};
// This does something interesting...
template<typename T>
void f(T const&);
int main() {
// fails to link - tries to get the address of "Foo::value"!
f(Foo::value);
// works - pass a temporary value
f(+Foo::value);
}
Decay an array to a pointer
Do you want to pass two pointers to a function, but it just won't work? The operator may help
// This does something interesting...
template<typename T>
void f(T const& a, T const& b);
int main() {
int a[2];
int b[3];
f(a, b); // won't work! different values for "T"!
f(+a, +b); // works! T is "int*" both time
}
Lifetime of temporaries bound to const references is one that few people know about. Or at least it's my favorite piece of C++ knowledge that most people don't know about.
const MyClass& x = MyClass(); // temporary exists as long as x is in scope
A nice feature that isn't used often is the function-wide try-catch block:
int Function()
try
{
// do something here
return 42;
}
catch(...)
{
return -1;
}
Main usage would be to translate exception to other exception class and rethrow, or to translate between exceptions and return-based error code handling.
Many know of the identity / id metafunction, but there is a nice usecase for it for non-template cases: Ease writing declarations:
// void (*f)(); // same
id<void()>::type *f;
// void (*f(void(*p)()))(int); // same
id<void(int)>::type *f(id<void()>::type *p);
// int (*p)[2] = new int[10][2]; // same
id<int[2]>::type *p = new int[10][2];
// void (C::*p)(int) = 0; // same
id<void(int)>::type C::*p = 0;
It helps decrypting C++ declarations greatly!
// boost::identity is pretty much the same
template<typename T>
struct id { typedef T type; };
A quite hidden feature is that you can define variables within an if condition, and its scope will span only over the if, and its else blocks:
if(int * p = getPointer()) {
// do something
}
Some macros use that, for example to provide some "locked" scope like this:
struct MutexLocker {
MutexLocker(Mutex&);
~MutexLocker();
operator bool() const { return false; }
private:
Mutex &m;
};
#define locked(mutex) if(MutexLocker const& lock = MutexLocker(mutex)) {} else
void someCriticalPath() {
locked(myLocker) { /* ... */ }
}
Also BOOST_FOREACH uses it under the hood. To complete this, it's not only possible in an if, but also in a switch:
switch(int value = getIt()) {
// ...
}
and in a while loop:
while(SomeThing t = getSomeThing()) {
// ...
}
(and also in a for condition). But i'm not too sure whether these are all that useful :)
Preventing comma operator from calling operator overloads
Sometimes you make valid use of the comma operator, but you want to ensure that no user defined comma operator gets into the way, because for instance you rely on sequence points between the left and right side or want to make sure nothing interferes with the desired action. This is where void() comes into game:
for(T i, j; can_continue(i, j); ++i, void(), ++j)
do_code(i, j);
Ignore the place holders i put for the condition and code. What's important is the void(), which makes the compiler force to use the builtin comma operator. This can be useful when implementing traits classes, sometimes, too.
Array initialization in constructor.
For example in a class if we have a array of int as:
class clName
{
clName();
int a[10];
};
We can initialize all elements in the array to its default (here all elements of array to zero) in the constructor as:
clName::clName() : a()
{
}
Oooh, I can come up with a list of pet hates instead:
Destructors need to be virtual if you intend use polymorphically
Sometimes members are initialized by default, sometimes they aren't
Local clases can't be used as template parameters (makes them less useful)
exception specifiers: look useful, but aren't
function overloads hide base class functions with different signatures.
no useful standardisation on internationalisation (portable standard wide charset, anyone? We'll have to wait until C++0x)
On the plus side
hidden feature: function try blocks. Unfortunately I haven't found a use for it. Yes I know why they added it, but you have to rethrow in a constructor which makes it pointless.
It's worth looking carefully at the STL guarantees about iterator validity after container modification, which can let you make some slightly nicer loops.
Boost - it's hardly a secret but it's worth using.
Return value optimisation (not obvious, but it's specifically allowed by the standard)
Functors aka function objects aka operator(). This is used extensively by the STL. not really a secret, but is a nifty side effect of operator overloading and templates.
You can access protected data and function members of any class, without undefined behavior, and with expected semantics. Read on to see how. Read also the defect report about this.
Normally, C++ forbids you to access non-static protected members of a class's object, even if that class is your base class
struct A {
protected:
int a;
};
struct B : A {
// error: can't access protected member
static int get(A &x) { return x.a; }
};
struct C : A { };
That's forbidden: You and the compiler don't know what the reference actually points at. It could be a C object, in which case class B has no business and clue about its data. Such access is only granted if x is a reference to a derived class or one derived from it. And it could allow arbitrary piece of code to read any protected member by just making up a "throw-away" class that reads out members, for example of std::stack:
void f(std::stack<int> &s) {
// now, let's decide to mess with that stack!
struct pillager : std::stack<int> {
static std::deque<int> &get(std::stack<int> &s) {
// error: stack<int>::c is protected
return s.c;
}
};
// haha, now let's inspect the stack's middle elements!
std::deque<int> &d = pillager::get(s);
}
Surely, as you see this would cause way too much damage. But now, member pointers allow circumventing this protection! The key point is that the type of a member pointer is bound to the class that actually contains said member - not to the class that you specified when taking the address. This allows us to circumvent checking
struct A {
protected:
int a;
};
struct B : A {
// valid: *can* access protected member
static int get(A &x) { return x.*(&B::a); }
};
struct C : A { };
And of course, it also works with the std::stack example.
void f(std::stack<int> &s) {
// now, let's decide to mess with that stack!
struct pillager : std::stack<int> {
static std::deque<int> &get(std::stack<int> &s) {
return s.*(pillager::c);
}
};
// haha, now let's inspect the stack's middle elements!
std::deque<int> &d = pillager::get(s);
}
That's going to be even easier with a using declaration in the derived class, which makes the member name public and refers to the member of the base class.
void f(std::stack<int> &s) {
// now, let's decide to mess with that stack!
struct pillager : std::stack<int> {
using std::stack<int>::c;
};
// haha, now let's inspect the stack's middle elements!
std::deque<int> &d = s.*(&pillager::c);
}
Another hidden feature is that you can call class objects that can be converted to function pointers or references. Overload resolution is done on the result of them, and arguments are perfectly forwarded.
template<typename Func1, typename Func2>
class callable {
Func1 *m_f1;
Func2 *m_f2;
public:
callable(Func1 *f1, Func2 *f2):m_f1(f1), m_f2(f2) { }
operator Func1*() { return m_f1; }
operator Func2*() { return m_f2; }
};
void foo(int i) { std::cout << "foo: " << i << std::endl; }
void bar(long il) { std::cout << "bar: " << il << std::endl; }
int main() {
callable<void(int), void(long)> c(foo, bar);
c(42); // calls foo
c(42L); // calls bar
}
These are called "surrogate call functions".
Hidden features:
Pure virtual functions can have implementation. Common example, pure virtual destructor.
If a function throws an exception not listed in its exception specifications, but the function has std::bad_exception in its exception specification, the exception is converted into std::bad_exception and thrown automatically. That way you will at least know that a bad_exception was thrown. Read more here.
function try blocks
The template keyword in disambiguating typedefs in a class template. If the name of a member template specialization appears after a ., ->, or :: operator, and that name has explicitly qualified template parameters, prefix the member template name with the keyword template. Read more here.
function parameter defaults can be changed at runtime. Read more here.
A[i] works as good as i[A]
Temporary instances of a class can be modified! A non-const member function can be invoked on a temporary object. For example:
struct Bar {
void modify() {}
}
int main (void) {
Bar().modify(); /* non-const function invoked on a temporary. */
}
Read more here.
If two different types are present before and after the : in the ternary (?:) operator expression, then the resulting type of the expression is the one that is the most general of the two. For example:
void foo (int) {}
void foo (double) {}
struct X {
X (double d = 0.0) {}
};
void foo (X) {}
int main(void) {
int i = 1;
foo(i ? 0 : 0.0); // calls foo(double)
X x;
foo(i ? 0.0 : x); // calls foo(X)
}
map::operator[] creates entry if key is missing and returns reference to default-constructed entry value. So you can write:
map<int, string> m;
string& s = m[42]; // no need for map::find()
if (s.empty()) { // assuming we never store empty values in m
s.assign(...);
}
cout << s;
I'm amazed at how many C++ programmers don't know this.
Putting functions or variables in a nameless namespace deprecates the use of static to restrict them to file scope.
Defining ordinary friend functions in class templates needs special attention:
template <typename T>
class Creator {
friend void appear() { // a new function ::appear(), but it doesn't
… // exist until Creator is instantiated
}
};
Creator<void> miracle; // ::appear() is created at this point
Creator<double> oops; // ERROR: ::appear() is created a second time!
In this example, two different instantiations create two identical definitions—a direct violation of the ODR
We must therefore make sure the template parameters of the class template appear in the type of any friend function defined in that template (unless we want to prevent more than one instantiation of a class template in a particular file, but this is rather unlikely). Let's apply this to a variation of our previous example:
template <typename T>
class Creator {
friend void feed(Creator<T>*){ // every T generates a different
… // function ::feed()
}
};
Creator<void> one; // generates ::feed(Creator<void>*)
Creator<double> two; // generates ::feed(Creator<double>*)
Disclaimer: I have pasted this section from C++ Templates: The Complete Guide / Section 8.4
void functions can return void values
Little known, but the following code is fine
void f() { }
void g() { return f(); }
Aswell as the following weird looking one
void f() { return (void)"i'm discarded"; }
Knowing about this, you can take advantage in some areas. One example: void functions can't return a value but you can also not just return nothing, because they may be instantiated with non-void. Instead of storing the value into a local variable, which will cause an error for void, just return a value directly
template<typename T>
struct sample {
// assume f<T> may return void
T dosomething() { return f<T>(); }
// better than T t = f<T>(); /* ... */ return t; !
};
Read a file into a vector of strings:
vector<string> V;
copy(istream_iterator<string>(cin), istream_iterator<string>(),
back_inserter(V));
istream_iterator
You can template bitfields.
template <size_t X, size_t Y>
struct bitfield
{
char left : X;
char right : Y;
};
I have yet to come up with any purpose for this, but it sure as heck surprised me.
One of the most interesting grammars of any programming languages.
Three of these things belong together, and two are something altogether different...
SomeType t = u;
SomeType t(u);
SomeType t();
SomeType t;
SomeType t(SomeType(u));
All but the third and fifth define a SomeType object on the stack and initialize it (with u in the first two case, and the default constructor in the fourth. The third is declaring a function that takes no parameters and returns a SomeType. The fifth is similarly declaring a function that takes one parameter by value of type SomeType named u.
Getting rid of forward declarations:
struct global
{
void main()
{
a = 1;
b();
}
int a;
void b(){}
}
singleton;
Writing switch-statements with ?: operators:
string result =
a==0 ? "zero" :
a==1 ? "one" :
a==2 ? "two" :
0;
Doing everything on a single line:
void a();
int b();
float c = (a(),b(),1.0f);
Zeroing structs without memset:
FStruct s = {0};
Normalizing/wrapping angle- and time-values:
int angle = (short)((+180+30)*65536/360) * 360/65536; //==-150
Assigning references:
struct ref
{
int& r;
ref(int& r):r(r){}
};
int b;
ref a(b);
int c;
*(int**)&a = &c;
The ternary conditional operator ?: requires its second and third operand to have "agreeable" types (speaking informally). But this requirement has one exception (pun intended): either the second or third operand can be a throw expression (which has type void), regardless of the type of the other operand.
In other words, one can write the following pefrectly valid C++ expressions using the ?: operator
i = a > b ? a : throw something();
BTW, the fact that throw expression is actually an expression (of type void) and not a statement is another little-known feature of C++ language. This means, among other things, that the following code is perfectly valid
void foo()
{
return throw something();
}
although there's not much point in doing it this way (maybe in some generic template code this might come handy).
The dominance rule is useful, but little known. It says that even if in a non-unique path through a base-class lattice, name-lookup for a partially hidden member is unique if the member belongs to a virtual base-class:
struct A { void f() { } };
struct B : virtual A { void f() { cout << "B!"; } };
struct C : virtual A { };
// name-lookup sees B::f and A::f, but B::f dominates over A::f !
struct D : B, C { void g() { f(); } };
I've used this to implement alignment-support that automatically figures out the strictest alignment by means of the dominance rule.
This does not only apply to virtual functions, but also to typedef names, static/non-virtual members and anything else. I've seen it used to implement overwritable traits in meta-programs.