Archive for 2016

Range-based for loop vs std::transform

Some time ago, while doing some code review in work I came across the problem whether the loop in the code I was reviewing should be expressed with std::for_each, std::transform or range-based for loop. The initial code looked pretty much like this:

1
2
3
4
5
6
7
8
std::vector<Type> destination;
destination.reserve(source.size());
 
std::for_each(std::begin(source), std::end(source), 
              [&destination](auto const& p_value)
{
    destination.push_back(SomeStruct{p_value.a, p_value.b, p_value.c});
});

The first things that come to my mind when I see such code are “Why are you using std::for_each? Shouldn’t you use range-based for loop?” Or maybe there should be a std::transform?” Let’s consider those three things:

std::for_each

This is an algorithm from standard library that represents standard for loop that goes over a range defined by begin and end iterator and runs given functor or function. An example of usage is presented above. It utilizes lambda expression that invokes push_back on a std::vector to add elements.

range-based for

Given algorithm can be easily converted to this new form of loop (introduced in C++11).

1
2
3
4
5
6
7
std::vector<Type> destination;
destination.reserve(source.size());
 
for(auto const& p_value : source) 
{
    destination.push_back(SomeStruct{p_value.a, p_value.b, p_value.c});
};

This is the same algorithm but in much clearer and less noisy form.

std::transform

Another considered algorithm is std::transform that is supposed to be used (as the name says) to transform one structure to another. Let’s convert given code to utilize this algorithm.

1
2
3
4
5
6
7
8
std::vector<Type> destination;
destination.reserve(source.size());
 
std::transform(std::begin(source), std::end(source), std::back_inserter(destination),
              [](auto const& p_value)
{
    return SomeStruct{p_value.a, p_value.b, p_value.c};
});

It looks pretty much like std::for_each. The difference is in the name, the third argument and that the lambda returns new value instead of inserting in into the new container.

To be honest, when I have to choose between those versions I would choose std::transform because of its explicitness. This algorithm just says what is done. It gets one array and transforms it into another. std::for_each and range-based-for are just simple loops with no more special meaning than “run this function over this array”. From the last two if I had to choose one, then I would prefer range-based-for since its very clean form of loop over an array (no additional noise in form of lambda or std::begin/std::end).

But…

Since we are considering C++11 there’s one more thing to consider when inserting elements into std::vectoremplace_back. If we have a class with constructor and emplace_back then situation changes, because emplace_back allows us to create objects right inside the vector’s memory. In that case using std::transform doesn’t allow such operation because it requires copy (inside std::back_inserter).

Let’s take look at the code with all scenarios:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <iostream>
#include <algorithm>
#include <vector>
 
struct TestStruct
{
    TestStruct(int a, std::string b)
        : m_a(a)
        , m_b(b)
    {
        std::cout << ">> Constructor: a=" << m_a << ", b=" << m_b << std::endl;
    }
 
    TestStruct(TestStruct const& src)
        : m_a(src.m_a)
        , m_b(src.m_b)
    {
        std::cout << ">> Copy Constructor: a=" << m_a << ", b=" << m_b << std::endl;
    }
 
    TestStruct(TestStruct && src)
        : m_a(src.m_a)
        , m_b(std::move(src.m_b))
    {
        std::cout << ">> Move Constructor: a=" << m_a << ", b=" << m_b << std::endl;
    }
 
    ~TestStruct()
    {
        std::cout << ">> Destructor: a=" << m_a << ", b=" << m_b << std::endl;
    }
 
private:
    int m_a;
    std::string m_b;
};
 
struct InputStruct
{
    int a;
    std::string b;
};
 
using namespace std;
 
int main(int argc, char *argv[])
{
    InputStruct input[] = {
        { 1, "one" },
        { 2, "two" },
    };
 
    std::cout << "std::for_each:" << std::endl;
 
    std::vector<TestStruct> va;
    va.reserve(std::end(input) - std::begin(input));
    std::for_each(std::begin(input), std::end(input),
                  [&va](auto const& p_in)
    {
        va.push_back(TestStruct{p_in.a, p_in.b});
    });
 
    std::cout << "\nrange-based-for:" << std::endl;
 
    std::vector<TestStruct> vb;
    va.reserve(std::end(input) - std::begin(input));
    for(auto const& p_in : input)
    {
        vb.push_back(TestStruct{p_in.a, p_in.b});
    }
 
    std::cout << "\nstd::transform:" << std::endl;
    std::vector<TestStruct> vc;
    vc.reserve(std::end(input) - std::begin(input));
    std::transform(std::begin(input), std::end(input), std::back_inserter(vc),
                  [](auto const& p_in)
    {
        return TestStruct{p_in.a, p_in.b};
    });
 
    std::cout << "\nrange-based-for + emplace_back:" << std::endl;
 
    std::vector<TestStruct> vd;
    vd.reserve(std::end(input) - std::begin(input));
    for(auto const& p_in : input)
    {
        vd.emplace_back(p_in.a, p_in.b);
    }
 
    std::cout << "\n\nDestruction of all items:" << std::endl;
}

The output is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
std::for_each:
>> Constructor: a=1, b=one
>> Move Constructor: a=1, b=one
>> Destructor: a=1, b=
>> Constructor: a=2, b=two
>> Move Constructor: a=2, b=two
>> Destructor: a=2, b=
 
range-based-for:
>> Constructor: a=1, b=one
>> Move Constructor: a=1, b=one
>> Destructor: a=1, b=
>> Constructor: a=2, b=two
>> Move Constructor: a=2, b=two
>> Destructor: a=2, b=
 
std::transform:
>> Constructor: a=1, b=one
>> Move Constructor: a=1, b=one
>> Destructor: a=1, b=
>> Constructor: a=2, b=two
>> Move Constructor: a=2, b=two
>> Destructor: a=2, b=
 
range-based-for + emplace_back:
>> Constructor: a=1, b=one
>> Constructor: a=2, b=two
 
 
Destruction of all items:
>> Destructor: a=1, b=one
>> Destructor: a=2, b=two
>> Destructor: a=1, b=one
>> Destructor: a=2, b=two
>> Destructor: a=1, b=one
>> Destructor: a=2, b=two
>> Destructor: a=1, b=one
>> Destructor: a=2, b=two

The output from the app reveals everything. The emplace_back version produces the smallest output, just as suspected, and all other loops does exactly the same thing.

What about POD?

Of course the previous version works smoothly only with classes that defines the constructor which can be used within emplace_back. When considering POD structs that doesn’t have one, the trick won’t work and won’t even compile. When adding POD object into vector it requires explicit use of the struct name when creating new objects that goes to the container.

In such case, in my opinion, the std::transform is the best way to express the intent.

Defined and not defined constructor in C++

C++ is a pretty interesting language because of different quirks that it has. One of such things is the fact that there is a difference between defined constructor, not defined constructor and deleted constructor, especially move constructor.

Consider following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
 
struct ExplicitMoveConstructor
{
    ExplicitMoveConstructor()
    {
        std::cout << "Default constructor" << std::endl;
    }
 
    ExplicitMoveConstructor(ExplicitMoveConstructor const& src)
    {
        std::cout << "Copy constructor" << std::endl;
    }
 
    ExplicitMoveConstructor(ExplicitMoveConstructor && src)
    {
        std::cout << "Move constructor" << std::endl;
    }
};
 
struct DeletedMoveConstructor
{
    DeletedMoveConstructor()
    {
        std::cout << "Default constructor" << std::endl;
    }
 
    DeletedMoveConstructor(DeletedMoveConstructor const& src)
    {
        std::cout << "Copy constructor" << std::endl;
    }
 
    DeletedMoveConstructor(DeletedMoveConstructor && src) = delete;
};
 
struct NotDefinedMoveConstructor
{
    NotDefinedMoveConstructor()
    {
        std::cout << "Default constructor" << std::endl;
    }
 
    NotDefinedMoveConstructor(NotDefinedMoveConstructor const& src)
    {
        std::cout << "Copy constructor" << std::endl;
    }
};
 
auto returnExplicitMoveConstructorClass()
{
    ExplicitMoveConstructor cm;
    return cm;
}
 
auto returnDeletedMoveConstructorClass()
{
    DeletedMoveConstructor cm;
    return cm;
}
 
auto returnNotDefinedMoveConstructorClass()
{
    NotDefinedMoveConstructor cm;
    return cm;
}
 
int main()
{
    auto first = returnExplicitMoveConstructorClass();
    auto second = returnDeletedMoveConstructorClass();
    auto third = returnNotDefinedMoveConstructorClass();
    return 0;
}

The presented code does not compile when trying to do so with following command:

clang++ constructor.cpp --std=c++14

The error code is as follows:

constructor.cpp:70:7: error: call to deleted constructor of 'DeletedMoveConstructor'
        auto second = returnDeletedMoveConstructorClass();
             ^        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
constructor.cpp:33:2: note: 'DeletedMoveConstructor' has been explicitly marked deleted here
        DeletedMoveConstructor(DeletedMoveConstructor && src) = delete;
        ^
1 error generated.

The error from the compiler says that the move constructor was called but it is marked as deleted. If compiled with g++ it’s pretty much the same.

Conclusions from this are two. The first one is that the deleted constructor is also a declared constructor so the compiler will use it as if it was defined by the user. The second one is that the value returned from function is returned by utilizing move semantic when move constructor is declared, even if it is deleted.

The explaination for this turns out to be quite simple. As written in this post on Stack Overflow, this is the intended behaviour of overload resolution. Since declared, the move constructor is the best match for value returned from function which is an r-value.

NAssist

This time I would like to publish my application that I wrote some time ago and I’ve been actively using. I call it NAssist. Purpose of this application is to provide an on demand window (accessed with global keyboard shortcut) that allows to enter some commands whose effects would be displayed inside it.

Basic application window

Basic application window

Application is written in Python 3 with PyQt5 and PyWin (for Windows) or python-xlib (for Linux). PyQt is used as an application framework while PyWin or python-xlib are needed for handling global hotkeys.

Usage

Global hotkeys are used to call application which is normally hidden in the background with icon in Notification Area or Tray (both on Windows and Linux). Application window can be called with predefined global hotkeys – CTRL + SHIFT + SPACE. On the other hand the window can be hidden with ESCAPE hotkey while focused.

Application in default mode appears only with one Command field which should be already focused by previously pressing mentioned hotkey combination (CTRL + SHIFT + SPACE). If it’s not, it can be made so by pressing them again. In this state application is ready to accept commands which are defined in __init__ function in mainwindow.py file. Those commands come from modules package.

Example of translation from English to Polish

Example of translation from English to Polish

Basic commands that come with the application are:

  • ap {text} – English -> Polish translator (google translate),
  • pa {text} – Polish -> English translator (google translate),
  • np {text} – German -> Polish translator (google translate),
  • pn {text} – Polish -> German translator (google translate),
  • sjp {word} – Polish language dictionary (sjp.pl).

To use one of those commands simply write them in Command field with arguments after space. The result of “ap I translate to Polish” is presented in the image on the right. As shown, the result appears right below the Command field, also the window is enlarged to make the result visible.

To quickly delete everything from Command field there is an additional hotkey – SHIFT + DELETE.

Writing own modules

Writing own modules is pretty straightforward. It requires a module to handle following events which are defined in BaseModule.py file:

  • onKeyPress(event) – key has been pressed inside application window, event represents PyQt event,
  • onTextUpdate(text) – argument text has been updated for given module (from command “ap text” only “text” will be passed,
  • onActivate() – current module has been activated,
  • onDeactivate() – current module has been deactivated (new module will be activated if command was changed, not removed),
  • onClose() – application is closing.

The basic commands are implemented using some more specialized base classes that are available for extension:

  • TranslatorModule – uses google translator to provide web page with results via “https://translate.google.com/#{}/{}/{}” pattern,
  • WebModule – is used to implement above module, can be used to add other webpages as commands.

Download and requirements

Application is already public on GitHub with GPL2 license.

Requirements for Windows:

Requirements for Linux:

  • Python 3
  • PyQt5 matching Python version
  • python3-xlib (pip install python3-xlib)