Copy elision and the (N)RVO

Featured

In C++, user defined types, by design, will have default behavior as primitive types do. This uniformity has many advantages, but it puts burden on the developer to decide how parameters are passed in and out of functions.

There are some optimizations which will be used to avoid unnecessary copying. Basically, there are two main categories:

  • Copy elision
  • Move semantics

Their understanding is crucial for your efficiency. Move semantics (introduced in C++0x, now in C++11) is maybe easier to understand because it has explicit language syntax and it is pretty much clear that every temporary (rvalue) and explicitly moved lvalue is a candidate for move construction.

On the other hand, copy elision is more subtle, it’s not mandatory by Standard and it’s compiler dependent optimization.

Continue reading

auto: Use, but don’t overuse

There are many new C++11 features, but one of them will be certainly used all the time. auto is a great little gem and it can reduce your code redundancy and make it less error-prone. You can use it in various places and contexts, but as it seems like it’s some kind of magic, pretty soon situation can be described with famous hammer-nail relationship: “If all you have is a hammer, everything looks like a nail”.

Continue reading

is_callable – part II

This entry is part of a series, is_callable»

In the previous post I said why the type traits are important and wrote is_callable trait that can detect potential callable types. It’s not perfect but it will suffice for the most common use cases.
is_callable has two template parameters: Callable, which is potentially callable type and Function is corresponding function signature that will be used to test Callable. We will try to “instantiate” Callable and simulate the calling with appropriate arguments. I am saying “simulate” because we won’t actually create any object (neither Callable nor arguments for potential call).

Continue reading

Entries in this series:
1. is_callable – part I
2. is_callable – part II
Powered by Hackadelic Sliding Notes 1.6.5

is_callable – part I

This entry is part of a series, is_callable»

Writing function and class templates is something you will almost always want to do using some form of type constraints, because unconstrained templates can be meaningless and sometimes dangerous when template parameters are substituted with “wrong” types.
Type traits are very helpful set of tools for type introspection and you should use them whenever you need to express constraints or introduce relations between types, but don’t overuse them.

Continue reading

Entries in this series:
1. is_callable – part I
2. is_callable – part II
Powered by Hackadelic Sliding Notes 1.6.5

Type inference for temporary objects in different contexts

One of the things I don’t like in C++ is his verbosity in some situations. You can easily get a headache from reading long lines of code that are actually very simple, but unnecessary complicated. In the earlier post, syntactic sugar for objects resetting with temporaries was briefly mentioned, but in fact you can use the same technique in various places leading to more readable code.
Continue reading

Using Qt signals with C++ lambdas

Qt signals and slots mechanism is awesome! You can use it to make really good event driven applications. I remember first time when I heard about lambda functions, but until year ago one thing didn’t cross my mind. Why can’t we use C++0x lambdas instead of classically implemented Qt slots? As a matter of fact, we can. It’ll be interesting to see new signals and slots syntax in Qt5, but for now we will stick with what we have.
Continue reading

Explicit specialization in non-namespace scope

If you try something like this:

#include <iostream>

struct A
{
    template<typename T, typename U>
    struct B
    {
        void f() { std::cout << "T, U" << std::endl; }
    };

    template<>
    struct B<int, float>
    {
        void f() { std::cout << "int, float" << std::endl; }
    };
};

int main()
{
    A::B<int, char> x;
    A::B<int, float> y;
}

…you’ll end up with Standard non-compliant code. Here’s what C++03 says:
C++03, §14.7.3/2:
An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member.
An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member.

Continue reading

Identity structure

Let’s start with a simple example:

#include <iostream>
#include <utility>

template<typename T>
void F(T x)
{
    std::cout << typeid(x).name() << std::endl;
}

int main()
{
    F(10.0);
    F(10.0f);
    F(10);

    return(0);
}

Ok, the result is obvious. If someone asks you what type is deduced for function argument in function F, you’ll know immediately each time when you see on of these function calls. In all three cases, function argument is very simple constant expression, but what if it’s not constant expression at all, or if it’s not simple expression but rather some complex constant expression?
Continue reading