I have a class which has a std::function as a member variable.
class Animal
{
public:
Animal(const std::function<double(const int x)> MakeNoise) : MakeNoise(MakeNoise) {}
void Print(const int x) { std::cout << this->MakeNoise(x) << std::endl; }
private:
const std::function<double(const int x)> MakeNoise;
int a = 4;
int b = 8;
int c = 12;
};
I would like to be able to swap out the MakeNoise function without subclassing Animal by passing various lambdas.
const auto MakeNoise1 = [this](const int x)
{
return a + b + x;
}
const auto MakeNoise2 = [this](const int x)
{
return a + b + c + x;
}
Is it possible to capture this if the definition of the function is in a different file?
Is it possible to use [&] (capture by reference) to capture x pass into Print ?
Lastly, is there a better way to define this class so I can swap the function in and out?
If I add this the compiler says error: invalid use of ‘this’ at top level which makes sense since the definition of the lambda is not within a class.
I do not think this is possible to do directly. After all, the lambdas as given don't know anything about Animal. You can work around it by having the function's signature be
(const Animal& animal, const int x) instead and accessing it through animal.
this is a special name inside member functions. If MakeNoise1 wants to capture this, it needs to be in a member of Animal. Your compiler told you so, and you interpreted that message corerctly.
That's not a big restriction, since Animal::a is private anyway.
You can define Animal methods in other .cpp files, but you'd still need to declare these methods in class Animal, so this might or might not match your larger design.
If you are defining the lambda outside a member function, then no, you cannot capture this because there is no this to capture. A capture is a way to provide access to variables that are defined at the point where the lambda is defined. A capture cannot capture things that do not exist at the point of capturing.
What you want to do is provide access to variables that are defined at the point where the lambda is invoked. This is the job of parameters, as in this->MakeNoise(this, x) or perhaps MakeNoise(*this, x). (Your Print wrapper can easily provide the extra parameter. In fact, adding parameters is a common motivation for writing wrapper functions.) However, I suspect that this might not be the best approach.
Instead of thinking about how to access this, think about what MakeNoise is supposed to do and what it needs to do that. Does it really need the entire Animal including private data? If so, it probably should be a member function. Bite the bullet and create a plethora of derived classes (and provide protected access to the data). Does it instead need the entire Animal, but only the public interface? If so, a lambda that takes both const Animal & and const int as parameters might be reasonable. Furthermore, it might be reasonable to expand the public interface to accommodate this.
Perhaps, though, you are in the case where MakeNoise does not really need an Animal so much as a few key bits of data. This is the point where you have to look at your design and your levels of abstraction. We cannot do this for you because, as is appropriate for a StackOverflow question, we do not have the complete picture. However, I can present for consideration the possibility that things other than animals can make a noise. Are your MakeNoise lambdas supposed to be abstract enough to not care what is making the noise? If so, you might consider adding specific data as parameters to your lambdas. Your Print function would become something more like the following.
void Print(const int x) { std::cout << MakeNoise(x, a, b, c) << std::endl; }
I am assuming that Animal has been (appropriately) simplified for this question, and that an Animal object really has a lot more data than a, b, and c. If this assumption is false, you are in the case of needing an entire Animal. However, if the parameters you would need to pass to MakeNoise are few in comparison to the data in Animal, this might be a better semantic fit to your design. Might. It all comes back to making design choices that are sensible and consistent. Think abstractly while avoiding over-engineering. Keep in mind that you need to provide the same parameters to each lambda (but the various lambdas can have different captures).
Here is an example lambda that could be used for this last approach, assuming the type of MakeNoise – both of the data member and of the parameter to the constructor – has been updated.
int main()
{
Animal cheetah{ [](int x, int a, int b, int c) -> double
{
return a + b + c + x;
}
};
cheetah.Print(2);
}
If you really want to use const int instead of int, you could. To me, it seems unnecessarily restrictive for a non-reference, but that's more style than substance.
I'm taking a C++ course and I'm stuck on classes and objects. I'm working on an assignment that, in a nutshell, creates a class that takes two variables (let's say length and width).
I've figured out how to do this using get and set functions. But then, we have to use math on these variables. We're supposed to write a function that takes one instance of the class as a parameter (so two variables), and then does math on both this object (the one taken as a parameter) and object that the method of was called.
Part of why I'm confused is the language, and I'm not sure exactly what that means. So far, like I said, I managed to be able to end up with setLength and setWidth variables set via user input. I am really, really stuck on trying to then pass these values (or this object?) to a function and then call the method of another object?
Maybe if someone could help me figure out what "taking an object as a parameter and then doing math on the object i called the method of" means? Or just help with passing objects?
Passing an object works just like passing other kinds of variables. If you were passing an integer into a function, you'd use this syntax for declaring the function:
void myFunction(int myInt);
and if you were passing in an object of class Foo, it would be:
void myOtherFunction(Foo myFoo);
This is sort of like saying, "This the thing I want you to use in your calculations. Copy the object I pass in here!. Passing by reference instead:
void myFunction(int &myInt);
void myOtherFunction(Foo &myFoo);
lets you modify the value you pass. It's also significantly cheaper with larger objects than passing by value which was the original syntax in this answer. You can think of it as you saying to the computer, "I know you want this value, but I'm not going to let you copy this. Just look over there, instead, and you'll find what I want you to work with." But sometimes you don't want to modify the thing you're working with!
Sure, you could be very careful in your function to avoid changing things, but the C++ language lets you say that you shouldn't modify the variable, and then will check that you don't modify it for you!
This can be accomplished by using
void yetAnotherFunction(const Foo &myFoo);
The const is what says "Don't let me be modified!" to the compiler, and the compiler will listen.
Say you want to assign a few values to a simple object, using a (non-member) function:
// a struct should usually hold simple groups of data,
// that don't do much by themselves. Their members are
// also public by default.
struct MySimpleType{
int first;
int second;
};
// object is passed by reference so it can be modified.
void modifier(MySimpleType &object, int newFirst, int newSecond){
object.first = newFirst;
object.second = newSecond;
}
then in your client code (probably a main function, at this point in your coding career) you do this:
MySimpleType object;
modifier(object, 13, 12);
cout << object.first << ", " << object.second;
which should print out:
13, 12
Thinking of pieces of code as "objects" can be difficult a first, but it will likely be one of the most important things you learn (because object oriented programming is widely used in industry and academia). There is quite a lot of background you need in order to use objects effectively in c++, but I'll try give a concise introduction..
Firstly, it's important that you understand the difference between a "class" and an "object." A class is an abstraction that allows you to define an object. If I want to make a Horse object, I use a Horse class to define what is important about a horse. This class might have fields defining its name, owner, hair color etc. However, the Horse class is not a horse. It tells you what it means to be a Horse, but it isn't one. In order to define an "object" of type Horse, we would write the following:
Horse myHorse = new Horse("Sea Biscuit", "Howard", "Black");
Keep in mind that Horse is the class, but Sea Biscuit is the horse itself (the object).
You may be well aware of the above, but it can often be a tough concept to grasp, so I thought I would mention it.
Now, if you want to perform math on some objects, this is relatively straightforward with using member functions. Lets define a new class to do some math on (because horses and math don't mix).
class Wallet
{
int _pennies;
// This is a constructor. It allows us to write: Wallet myWallet(100);
public Wallet(int pennies)
{
_pennies = pennies;
}
public void addPennies(int pennies)
{
_pennies = _pennies + pennies;
}
public void stealPennies(Wallet &stolenWallet)
{
int stolenPennies = stolenWallet._pennies;
stolenWallet._pennies = 0;
this.addPennies(stolenPennies);
}
}
We can now make some objects, and modify the fields in both objects with a single call to stealPennies:
int main()
{
Wallet myWallet(10); // Creates a wallet with 10 cents.
Wallet anotherWallet(50); // Creates another wallet with 50 cents.
myWallet.stealPennies(anotherWallet);
// myWallet now has 60 cents, and anotherWallet has none.
}
Note: The & before the name of the argument in the stealPennies function means it will be passed by reference. Usually when you pass an argument to a function it is passed by value, which means the variable in the function is a copy of the argument you passed. Putting the & before the name of the argument means the variable in the function is the same variable instead of a copy. (This is highly simplified.. it's unlikely that you will be able to fully understand passing by reference until you become familiar with pointers). Also, it is common practice to use some kind of naming convention when defining variables that are part of a class. Putting an underscore before the variable name is common (such as _pennies in this example).
Hopefully this is helpful to you (and hopefully it works, as I can't test it at the moment). I have tried to make the code as readable and explicit as possible.
As from your comment:
" I can't seem to figure out how to "assign" this user input to the object. So in the example above, i have setLength variables taken from user input. I cant figure out how to assign these variables to a new object, so that then the object is passes, the user input ( in the form of variables) is passed along with it!"
What I think you actually need is some function(s) to manipulate your class member variables by reading from a std::istream, and passing the object instance targeted as a reference:
class foo {
public:
foo() : x(12), y(42.0) {}
private:
friend std::istream& operator>>(std::istream& is, foo& subject);
std::istream& getfrominstream (std::istream& is) {
is >> x;
is >> y;
return is;
}
int x;
double y;
};
std::istream& operator>>(std::istream& is, foo& subject) {
return subject.getfrominstream(is);
}
Call like:
int main() {
foo f;
std::cin >> f;
}
suppose we have a class
class Foo {
private:
int PARTS;
public:
Foo( Graph & );
int howBig();
}
int Foo::howBig() { return this->PARTS; }
int Foo::howBig() { return PARTS; }
Foo::Foo( Graph &G ) {
<Do something with G.*>
}
Which one of howBig()-variants is correct?
The &-sign ensures that only the reference for Graph object
is passed to initialization function?
In C I would simply do something like some_function( Graph *G ),
but in C++ we have both & and *-type variables, never understood
the difference...
Thank you.
When you've local variable inside a member function, then you must have to use this as:
Foo::MemberFunction(int a)
{
int b = a; //b is initialized with the parameter (which is a local variable)
int c = this->a; //c is initialized with member data a
this->a = a; //update the member data with the parameter
}
But when you don't have such cases, then this is implicit; you need to explicity write it, which means in your code, both versions of howBig is correct.
However, in member initialization list, the rules are different. For example:
struct A
{
int a;
A(int a) : a(a) {}
};
In this code, a(a) means, the member data a is being initialized with the parameter a. You don't have to write this->a(a). Just a(a) is enough. Understand this visually:
A(int a) : a ( a ) {}
// ^ ^
// | this is the parameter
// this is the member data
You can use this-> to resolve the dependent name issue without explicitly having to spell out the name of the base. If the name of the base is big this could arguably improve readability.
This issue only occurs when writing templates and using this-> is only appropriate if they're member functions, e.g.:
template <typename T>
struct bar {
void func();
};
template <typename T>
struct foo : public bar {
void derived()
{
func(); // error
this->func(); // fine
bar<T>::func(); // also fine, but potentially a lot more verbose
}
};
Which one of howBig()-variants is correct?
both in your case, the compiler will produce the same code
The &-sign ensures that only the reference for Graph object is passed to initialization function? In C I would simply do something like some_function( Graph *G ), but in C++ we have both & and *-type variables, never understood the difference...
there is no difference as per the use of the variable inside the method(except syntax) - in the case of reference(&) imagine as if you've been passed an invisible pointer that you can use without dereferencing
it(the &) might be "easier" for clients to use
Both forms of Foo::howBig() are correct. I tend to use the second in general, but there are situations that involve templates where the first is required.
The main difference between references and pointers is the lack of "null references". You can use reference arguments when you don't want to copy the whole object but you want to force the caller to pass one.
Both are correct. Usually shorter code is easier to read, so only use this-> if you need it to disambiguate (see the other answers) or if you would otherwise have trouble understanding where the symbol comes from.
References can't be rebound and can't be (easily) bound to NULL, so:
Prefer references to pointers where you can use them. Since they cannot be null and they cannot be deleted, you have fewer things to worry about when using code that uses references.
Use const references instead of values to pass objects that are large (more than say 16 or 20 bytes) or have complex copy constructors to save copy overhead while treating it as if it was pass by value.
Try to avoid return arguments altogether, whether by pointer or reference. Return complex object or std::pair or boost::tuple or std::tuple (C++11 or TR1 only) instead. It's more readable.
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.