I am coding a C++ library and one class has two member functions that only differ in one function call:
int MyClass::member_func_1(int a) {
// ...
int b = some_function();
// ...
}
int MyClass::member_func_2(int a) {
// ...
int b = some_other_function();
// ...
}
Is there a way of not having to duplicate the code of these two functions, while still keeping the two member functions with the same function signatures?
Since it is a library all code must be generated when the library is compiled.
I have ruled out the option of having only one member function with an extra boolean argument to choose between some_function and some_other_function for performance reasons.
I know how to use a macro to do it, but could a template be used, or is there another better way?
A template solution is only a good solution if the call to either of the member functions is executed in a tight loop, where the overhead of testing a boolean or making an indirect function call would be too costly.
In this case, if C++17 standard is an option, the if constexpr syntax is probably the simplest way. Like in:
class MyClass
{
template<bool other> int member_func(int a)
{
//...
int b;
if constexpr (other)
b = some_other_function();
else
b = some_function();
//...
}
};
Since the only difference in the implementation of your two member functions is the calls to different member functions, that's what you should abstract out of those functions. You can do that by writing a single member function that takes a pointer to member function as an additional argument:
int common_member_func(int a, int (MyClass::*func)())
{
// ...
int b = (this->*func)();
// ...
}
and now the implementation of your two member functions would be:
int member_func_1(int a)
{
return common_member_func(a, &MyClass::some_function);
}
int member_func_2(int a)
{
return common_member_func(a, &MyClass::some_other_function);
}
Here's a demo.
You may use a boolean for switching the internal method to be called or pass a function pointer / std::function and call that one directly. the performance penalty will be ridiculously negligible.
If you really want to make your code less readable because of that virtually non-existant "performance reason", you can implement the common method templated, with a boolean template parameter. The if() clause referring the template parameter can then be a constexpr (realised during compilation).
However note that this will also lead to the method being effectively doubled in your applications code, and when you have many alternating calls, this might have an adverse effect on your performance similar to the original if() clause, i.e. not noticable at all.
I know using macros is "generally" not considered good programming practise but I will like to know how macros are defined for operators. For example, several boost libraries have macros that can be used as (http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/log/detailed/sources.html):
BOOST_LOG(m_logger)<< "Message to log";
I have tried to look at the definition of the BOOST_LOG but that is also pointing to a different macro, which also point to another etc until I get to:
#define BOOST_LOG_STREAM_INTERNAL(logger, rec_var)\
for (::boost::log::record rec_var = (logger).open_record(); !!rec_var;)\
::boost::log::aux::make_record_pump((logger), rec_var).stream()
My question is, if I have an operator << on a class, how can I turn it into a micro so I can do:
MY_MACRO << message.
Yes you can do this.
MY_MACRO would evaluate to the instantiation of a class, say Foo.
So MY_MACRO << message becomes Foo() << message; after the preprocessor has done its job.
Foo then defines an overloaded << operator for types such as const char*, which accumulates the result. Furthermore, Foo has a destructor that actually outputs those accumulated results. This will be called once the anonymous temporary Foo has gone out of scope which will happen at the end of the statement.
As you've noted, macros are usually best avoided in C++.
However, to indulge your curiosity (I do not recommend such things) .....
To do this, the macro would need to expand (eventually) to either (1) the name of (or maybe a reference to) an existing object that is in scope or (2) an expression that instantiates an object.
In both cases, the object would need to be of a type that has a suitable operator<<().
An example of the first is
#include <iostream>
#define A_MACRO std::cout
int main()
{
A_MACRO << "Hello world\n"; // will write to std::cout
}
A partial example of the second is
class X
{
public:
X() { /* set things up */ };
X &operator<<(const char * s)
{
// do something with s
return *this;
};
~X()
{
// clean up whatever resources (file handles, etc) the constructor set up
};
};
#define B_MACRO(SOMETHING) SOMETHING()
int main()
{
B_MACRO(X) << "Hello world\n";
}
(This is partial, because X would, presumably, need to do something useful which I haven't implemented). This example requires the macro argument to be a type that has both a default argument and suitable operator<<(). The operator<<() may be either a member of a class (as I've done it above), a non-member friend function, or a non-member function that only accesses public members of X.
To understand better, read up on how the preprocessor works (e.g. how it goes about handling macros that expand to use of other macros, and how it handles macro arguments).
Practically, avoid doing this where possible in C++, The occasions you need to are rare (e.g. if you're writing a library that, like Boost, must work for a range of compilers with different features and bugs). Macros have a pile of undesirable traits, including ignoring scope. You would usually be better off using objects or types directly, than hiding their usage in a set of macros.
You can't use characters other than letters, numbers, and the dollar sign (which is not guaranteed to be supported by the standard) in creating macros. The libraries you are talking about might be wrapping whatever arguments it receives into a class with an overloaded >> operator.
For example:
class wrapper {
int convertedType[];
public:
wrapper(aClassType a) {
//Convert a to an array of integers
}
static wrapper createWrapper(aClassType a) {
//Do the same thing as the constructor
}
aClassType toOriginalType(wrapper a) {
//perform conversion to wrapper
}
operator<< {
//perform operations on the converted type (int array in this example
}
}
#define MACRO(x) wrapper::toOriginalType(wrapper::createWrapper(x) << 5)
If you create enough conversion methods, then it will be as if >> can be used in macros.
I want to make a function which can handle different kind of things depend on type all in one.
I know Overloading is a nice solution for it. Just like,
class C1 {...};
class C2 {...};
void handle(C1& c1){...}
void handle(C2& c2){...}
But there are so many duplicated code in Overloading way since these 2 initialization is the same. That's why I want to wrap them together.
I have some ideas for my purpose.
For example,
class C1 {...};
class C2 {...};
void handle_C1(C1 &c1);
void handle_C2(C2 &c2);
template<typename T>
void handle(T &content){
// Initialization was done here
if (std::is_same(C1, T))
handle_C1(content);
if (std::is_same(C2, T))
handle_C2(content);
}
A compilation error was found error that handle_C2 mismatch parameters because handle_C2 parameter type is C2 when I call
C1 c1;
handle_C1<C1>(c1);
According to SFINAE in C++, I expect the compile would ignore this substitution failed, but it doesn't.
Is there anyone can give me a advice?
Is the best solution overloading? if it's true, how can I reduce my duplicated code.
It seems to me you are overthinking the problem. Simply define overloads without the initialization code and define a handle function that takes advantage of overload resolution.
class C1 {...};
class C2 {...};
void handle_impl(C1& c1){...} // Remove initialization from your overloads
void handle_impl(C2& c2){...}
template<typename T>
void handle(T &content)
{
// Initialization is done here
// Let the compiler resolve overloads for you
handle_impl(content);
}
When handle() is instantiated with a T, the full body of the function is instantiated. Both of the "if"s and their bodies are compiled. While you and I know that is_same() is a compile time constant and you may expect the compiler to ignore the impossible case, the way it's used is as a runtime value and the compiler must process both ifs and semantically checked "as if" they were both potentially called (even if the optimizer can eliminate one, that's after the validity testing the compiler does.) You thus end up with code calling handle_C1 and handle_C2, both passed the same type, and one is sure to be invalid and fail to compile.
If you can use c++17, a new feature directly addresses this problem, called "constexpr if" which makes the body of the if get processed (aside from valid statements and syntax) if the constexpr is true:
template<typename T>
void handle(T &content){
// Initialization was done here
if constexpr (std::is_same(C1, T))
handle_C1(content);
else if constexpr (std::is_same(C2, T))
handle_C2(content);
}
If you don't have a c++17 compiler, (or even if you do!) you should consider going back to your original design and simply factor out the initialization from each of the functions and make it a generic helper function.
I think in your case overloading is all you need. Simply write another method for you special initialization that handles each class and do your general stuff in the templated version (online):
void handleSpecial(C1& c1) {
std::cout << "Handling C1\n";
}
void handleSpecial(C2& c2) {
std::cout << "Handling C2\n";
}
template <typename T>
void handle(T& content) {
std::cout << "Doing generell stuff\n";
handleSpecial(content);
}
SFINAE only works before choosing which function to call, which in this case can't happen because the function can be called with any type. Then the whole body will be generated and you get the compiler error, because there's no function handle_C1 for C2 and vice versa.
Going through your steps:
If you have multiple classes that are handled the same for many things, but have individual character, then this could call for a base class. E.g. You could have something like:
class CBase { ... common features of C1, C2, C3, ...
public:
~CBase() {};
virtual void handle() = 0;
};
class C1 : public CBase { ... something specific to C1
public:
virtual void handle() { do what has to be done for C1 }
};
class C2 : public CBase { ... something specific to C2
public:
virtual void handle() { do what has to be done for C2 }
};
Now, it sounds a bit like this would already solve the issue, since you can call C1.handle() or CBase->handle(). If you need it to be done through an external function, you could do:
void handle(CBase *base_ptr) {
base_ptr->handle();
}
Personally, I find this nicer than passing by non-const reference anyways, but I know that this is a big debate.
About your SFINAE:
SFINAE just says that if the template substitution fails, the compiler will keep looking for a match and not throw an error directly. But it will throw an error if it does not find a match at all. In your case, if e.g. T = C2, it will still try to compile handle_C1(C2), which fails. (Your "if case" is a run-time decision, whereas the compiler makes these decisions at compile time)
You could revert to the good old pointer aliasing. It is allowed to cast a pointer to a type to a pointer to another type, it is simply UB to derefence a pointer if the value pointed has not the correct type.
But here you know that at run time the type will be correct, because the std::is_same guarantees it. So I would write:
template<typename T>
void handle(T &content){
// Initialization was done here
if (std::is_same<C1, T>()) {
C1* c = reinterpret_cast<C1*>(&content);
handle_C1(*c);
}
if (std::is_same<C2, T>()) {
C2* c = reinterpret_cast<C2*>(&content);
handle_C2(*c);
}
}
It just costs an automatic pointer allocation and copy that a really clever optimizing compiler could avoid because at low level machine code it is clearly a no-op.
Here's another solution that simply extracts the code common to both behaviors into its own function:
class C1 { /* ... */ };
class C2 { /* ... */ };
template<typename T>
void handle_init(T& content) {
// Common initialization code
}
void handle(C1& c1) {
handle_init(c1);
// C1-specific code
}
void handle(C2& c2) {
handle_init(c2);
// C2-specific code
}
Depending on the code inside handle_init, the template might not be necessary if, for example, the body of the function only calls "getter" methods of content, which can instead be called beforehand and passed to handle_init by the handle functions.
I named both functions handle to be consistent with the code you provided, but you can give them different names and it will still work for most use cases. This is the case for most uses of overloading, since overload resolution uses the compile-time type of the argument, which you as the programmer usually know anyways at the invocation site.
A big exception to this is if the argument to handle is a template parameter, in which case you'd need to use overloading (so some of the other answers actually do require overloading because of this). Note that to call different functions based on the run-time type of an argument, overloading doesn't work and you'd need virtual methods like in Cedric's answer.
But aside from the above paragraph, there isn't really a difference in functionality between having one function that handles arguments of different types, and having different functions for each argument type. Of course, maybe in your problem domain it makes sense to think of it as the former. And calling both functions handle using overloading would provide a notational convenience. I just think it's good to be consciously aware of this when doing it, in case it turns out that overloading doesn't have the functionality you need.
From the wikipedia article about Lambda functions and expressions:
users will often wish to define predicate functions near the place
where they make the algorithm function call. The language has only one
mechanism for this: the ability to define a class inside of a
function. ... classes defined in functions do not permit them to be used in templates
Does this mean that use of nested structure inside function is silently deprecated after C++0x lambda are in place ?
Additionally, what is the meaning of last line in above paragraph ? I know that nested classes cannot be template; but that line doesn't mean that.
I'm not sure I understand your confusion, but I'll just state all the facts and let you sort it out. :)
In C++03, this was legal:
#include <iostream>
int main()
{
struct func
{
void operator()(int x) const
{
std::cout << x << std::endl;
}
};
func f; // okay
f(-1); // okay
for (std::size_t i = 0; i < 10; ++i)
f(i) ; // okay
}
But if we tried doing this, it wasn't:
template <typename Func>
void exec(Func f)
{
f(1337);
}
int main()
{
// ...
exec(func); // not okay, local classes not usable as template argument
}
That left us with an issue: we want to define predicates to use for this function, but we can't put it in the function. So we had to move it to whatever outer scope there was and use it there. Not only did that clutters that scope with stuff nobody else needed to know about, but it moved the predicate away from where it's used, making it tougher to read the code.
It could still be useful, for the occasional reused chunk of code within the function (for example, in the loop above; you could have the function predicate to some complex thing with its argument), but most of the time we wanted to use them in templates.
C++0x changes the rules to allow the above code to work. They additionally added lambdas: syntax for creating function objects as expressions, like so:
int main()
{
// same function as above, more succinct
auto func = [](int x){ std::cout << x << std::endl; };
// ...
}
This is exactly like above, but simpler. So do we still have any use for "real" local classes? Sure. Lambda's fall short of full functionality, after all:
#include <iostream>
template <typename Func>
void exec(Func func)
{
func(1337);
}
int main()
{
struct func
{
// note: not possible in C++0x lambdas
void operator()(const char* str) const
{
std::cout << str << std::endl;
}
void operator()(int val) const
{
std::cout << val << std::endl;
}
};
func f; // okay
f("a string, ints next"); // okay
for (std::size_t i = 0; i < 10; ++i)
f(i) ; // okay
exec(f); // okay
}
That said, with lambda's you probably won't see local classes any more than before, but for completely different reasons: one is nearly useless, the other is nearly superseded.
Is there any use case for class inside function after introduction of lambda ?
Definitely. Having a class inside a function is about:
localising it as a private implementation detail of the code intending to use it,
preventing other code using and becoming dependent on it,
being independent of the outer namespace.
Obviously there's a threshold where having a large class inside a function harms readability and obfuscates the flow of the function itself - for most developers and situations, that threshold is very low. With a large class, even though only one function is intended to use it, it may be cleaner to put both into a separate source file. But, it's all just tuning to taste.
You can think of this as the inverse of having private functions in a class: in that situation, the outer API is the class's public interface, with the function kept private. In this situation, the function is using a class as a private implementation detail, and the latter is also kept private. C++ is a multi-paradigm language, and appropriately gives such flexibility in modelling the hierarchy of program organisation and API exposure.
Examples:
a function deals with some external data (think file, network, shared memory...) and wishes to use a class to represent the binary data layout during I/O; it may decide to make that class local if it only has a few fields and is of no use to other functions
a function wants to group a few items and allocate an array of them in support of the internal calculations it does to derive its return value; it may create a simple struct to wrap them up.
a class is given a nasty bitwise enum, or perhaps wants to reinterpret a float or double for access to the mantisa/exponent/sign, and decides internally to model the value using a struct with suitable-width bitfields for convenience (note: implementation defined behaviours)
classes defined in functions do not permit them to be used in templates
I think you commented that someone else's answer had explained this, but anyway...
void f()
{
struct X { };
std::vector<X> xs; // NOPE, X is local
}
Defining structures inside functions was never a particularly good way to deal with the lack of predicates. It works if you have a virtual base, but it's still a pretty ugly way to deal with things. It might look a bit like this:
struct virtual_base {
virtual void operator()() = 0;
};
void foo() {
struct impl : public virtual_base {
void operator()() { /* ... */ }
};
register_callback(new impl);
}
You can still continue to use these classes-inside-functions if you want of course - they're not deprecated or crippled; they were simply restricted from the very start. For example, this code is illegal in versions of C++ prior to C++0x:
void foo() {
struct x { /* ... */ };
std::vector<x> y; // illegal; x is a class defined in a function
boost::function<void()> z = x(); // illegal; x is used to instantiate a templated constructor of boost::function
}
This kind of usage was actually made legal in C++0x, so if anything the usefulness of inner classes has actually be expanded. It's still not really a nice way of doing things most of the time though.
Boost.Variant.
Lambdas don't work with variants, as variants need objects that have more than one operator() (or that have a templated operator()). C++0x allows local classes to be used in templates now, so boost::apply_variant can take them.
As Tony mentioned, a class inside a function is not only about predicates. Besides other use cases, it allows to create a factory function that creates objects confirming to an interface without exposing the implementing class. See this example:
#include <iostream>
/* I think i found this "trick" in [Alexandrescu, Modern C++ Design] */
class MyInterface {
public:
virtual void doSomethingUseful() = 0;
};
MyInterface* factory() {
class HiddenImplementation : public MyInterface {
void doSomethingUseful () {
std::cout << "Hello, World!" << std::endl;
}
};
return new HiddenImplementation();
}
int main () {
auto someInstance = factory();
someInstance->doSomethingUseful();
}
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.