neutrofoton

Science, Technology and Life

Working With Multiple Github Account on a Computer

| Comments

Source control is one of a basic need for software development, especially when we work on a team. Git is one of popular distributed source control. Working with multiple github account on the same computer need a few tricky way. Let’s assume we have cloned the repository from github to local computer. The following ways are the simple ways I got on internet.

Change Remote URL to HTTPS

This way is by changing the remote URL to HTTPS with the following format.

1
$ git remote set-url origin https://USERNAME@github.com/USERNAME/PROJECTNAME.git

Then do normal git operation such as commit, push etc. To ensure that the commits appear as performed by USERNAME, we can configure the username and email on our working directory.

1
2
$ git config user.name USERNAME
$ git config user.email USERNAME@example.com

Multiple SSH Key

The other way is by using multiple SSH key. Here is the complete tutorial by Jeffrey Way

References

  1. http://stackoverflow.com/questions/3860112/multiple-github-accounts-on-the-same-computer
  2. https://code.tutsplus.com/tutorials/quick-tip-how-to-work-with-github-and-multiple-accounts--net-22574

C++ Set With Custom Comparator

| Comments

std::set is a C++ STL container that store unique elements following a specific order. It is defined in the set header file.

Benefits and Features of std::set[3]:

  1. It’s doesn’t allow duplicate elements i.e. it only contains unique elements
  2. std::set can contain element of any specified type in template argument
  3. std::set internally store elements in balanced binary tree
  4. By default std::set uses the operator < for comparing two elements and but if user passes the external sorting criteria i.e. comparator then it uses it instead of default operator < .
  5. std::set will keep the inserted elements in sorted order based on the assigned sorting criteria i.e. either by default criteria operator < or by passed comparator (if passed).
  6. In this post the samples only limited to std::set that use custom comparator and store complex object instead of basic data type. The complex object that we will use is reusing class Person on previous post.

    Let’s create custom class that handles comparation process

    CustomCompare
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    #ifndef CustomCompare_h
    #define CustomCompare_h
    
    #include "Person.hpp"
    
    struct CustomCompare
    {
        bool operator()(const int& lhs, const int& rhs)
        {
            return lhs < rhs;
        }
    
        bool operator()(const Person& lhs, const Person& rhs)
        {
            return lhs.getAge() < rhs.getAge();
        }
    };
    
    #endif / CustomCompare_h /
    

    The following code is an example how to use the comparator class in std:set

    sample how to use
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    void SampleSetWithCustomCompare()
    {
        set<Person,CustomCompare> setOfPersons;
    
        setOfPersons.insert(Person("Person 1", 25));
        setOfPersons.insert(Person("Person 2", 16));
        setOfPersons.insert(Person("Person 3", 28));
        setOfPersons.insert(Person("Person 4", 9));
    
        for(set<Person,CustomCompare>::iterator it = setOfPersons.begin(); it!=setOfPersons.end(); ++it)
        {
            cout << it->getName() << " , age : " << it->getAge()<< endl;
        }
    
    }
    

    References

    1. http://www.cplusplus.com/reference/set/set/
    2. http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2nd-Edition.productCd-0470932449.html
    3. http://thispointer.com/stdset-tutorial-part-1-set-usage-details-with-default-sorting-criteria/

C++ Priority Queue With Comparator

| Comments

priority_queue is categorized as a STL container adaptor. It is like a queue that keeps its element in sorted order. Instead of a strict FIFO ordering, the element at the head of the queue at any given time is the one with the highest priority.

The template class definition of priority_queue is as follow

template definition
1
2
3
4
5
template <
   class Type,
   class Container=vector<Type>,
   class Compare=less<typename Container::value_type> >
class priority_queue

A user-provided compare can be supplied to change the ordering, e.g. using std::greater would cause the smallest element to appear as the top(). We also can create custom comparator for our need.

Many samples available on net about priority_queue with default compare parameter. In this article let’s create samples by specifying the compare parameter template.

priority_queue with std::greater
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//helper function displays sorted data
template<class T>
void printQueue(T& q)
{
    while (!q.empty())
    {
        cout << q.top() << endl;
        q.pop();
    }
}

void SamplePriorityQueue()
{
    std::priority_queue<int, std::vector<int>, std::greater<int> > q;

    for(int n : {1,8,5,6,3,4,0,9,7,2})
        q.push(n);

    printQueue(q);
}

The code above uses std::greater as a compare parameter template.

output
1
2
3
4
5
6
7
8
9
10
0
1
2
3
4
5
6
7
8
9

Beside the std::less or std::greater, we can create our custom comparator with lamda or custom class or struct.

lamda as compare parameter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void SamplePriorityQueueWithLamda()
{
    // using lambda to compare elements.
    auto compare = [](int lhs, int rhs)
                {
                    return lhs < rhs;
                };

    std::priority_queue<int, std::vector<int>, decltype(compare)> q(compare);

    for(int n : {1,8,5,6,3,4,0,9,7,2})
        q.push(n);


    printQueue(q);
}

To use the custom comparator, we just need to pass it as the third parameter of priority_queue template

custom comparator
1
2
3
4
5
6
7
struct CustomCompare
{
    bool operator()(const int& lhs, const int& rhs)
    {
        return lhs < rhs;
    }
};
sample with custom comparator
1
2
3
4
5
6
7
8
9
10
11
void SamplePriorityQueueWithCustomComparator()
{
    priority_queue<int,vector<int>, CustomCompare > pq;

    pq.push(3);
    pq.push(5);
    pq.push(1);
    pq.push(8);

    printQueue(pq);
}

The data stored in priority_queue is not limited to basic data type. We can store object in it. Let’s create a sample of it. Let’s say we have a Person class.

Person.hpp
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
#ifndef Person_hpp
#define Person_hpp

#include <stdio.h>
#include <string>

using namespace std;

class Person
{
public:
    Person();
    Person(string name, int age);
    virtual ~Person();

    string getName() const;
    int getAge() const;

    friend bool operator < (const Person& lhs, const Person& rhs);
    friend bool operator > (const Person& lhs, const Person& rhs);

private:
    string name;
    int age;
};

#endif /* Person_hpp */
Person.cpp
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
#include "Person.hpp"

bool operator < (const Person& lhs, const Person& rhs)
{
    return lhs.getAge() < rhs.getAge();
}

bool operator > (const Person& lhs, const Person& rhs)
{
    return lhs.getAge() > rhs.getAge();
}

Person::Person()
{
}

Person::Person(string name, int age):name(name), age(age)
{
}

Person::~Person()
{
}

string Person::getName() const
{
    return name;
}

int Person::getAge() const
{
    return age;
}

On the Person class, we have friend overloading methods, right angle bracket and left angle bracket. The methods act as comparation operator. The operator overloading is needed if we want to use std::less or std::greater.

sample priority_queue stores object
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
void SamplePriorityQueueStoreObject()
{
    vector<Person> personVector =
    {
        Person("Person 1", 25),
        Person("Person 2", 17),
        Person("Person 3", 35),
        Person("Person 4", 7),
        Person("Person 5", 50)
    };

    cout << "======== Less Priority Queue ======= " << endl;

    priority_queue<Person, vector<Person>, less<vector<Person>::value_type>> pqueue_less;

    //fill pqueue_less
    for (auto it = personVector.cbegin(); it!=personVector.cend(); it++)
    {
        pqueue_less.push(*it);
    }

    //iterate,display and pop
    while (!pqueue_less.empty())
    {
        Person value = pqueue_less.top();
        cout << value.getName() << " : " << value.getAge() << endl;

        pqueue_less.pop();
    }


    cout << endl << endl;

    cout << "======== Greater Priority Queue ======= " << endl;

    priority_queue<Person, vector<Person>, greater<vector<Person>::value_type>> pqueue_greater;
    //fill pqueue_greater
    for (auto it = personVector.cbegin(); it!=personVector.cend(); it++)
    {
        pqueue_greater.push(*it);
    }

    //iterate,display and pop
    while (!pqueue_greater.empty())
    {
        Person value = pqueue_greater.top();
        cout << value.getName() << " : " << value.getAge() << endl;

        pqueue_greater.pop();
    }
}

References

  1. http://en.cppreference.com/w/cpp/container/priority_queue
  2. https://support.microsoft.com/en-us/kb/837697
  3. http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2nd-Edition.productCd-0470932449.html

Reset Git Credential on OS X Keychain

| Comments

This post basically just a note for my self. In case I got the same condition in the next, it can help me to remember what I did in the past.

I got a condition which I have just changed my git password. Surely I cannot pull or push since my local credential was not valid anymore. When I run git config –list, I believe my git password stored on OS X Keychain. The simple way I do was running a command via terminal :

1
$ git config credential.helper osxkeychain

I was then prompted to input my username and password. By inputing my username and new password everything back to normal.

If you want it to apply globally just append parameter –global to the command.

1
$ git config --global credential.helper osxkeychain

References

  1. http://stackoverflow.com/questions/20195304/how-to-update-password-for-git

Ubuntu Server Does Not Recognize VirtualBox Adapter

| Comments

As we know, VirtualBox provides several adapters that we can add and be used by OS guest. At the time of writing this post, I have an OS X (host) and Ubuntu Server 16.04.1 LTS (guest). The needs are, I want to be able to remote my Ubuntu from OS X terminal. I also want my Ubuntu guest can connect to internet. I have configured two network adapters for the guest (NAT and host-only).

When I run

1
$ ifconfig

The first/default adapter (NAT) enp0s3 is recognized without any problems by the guest. But not the second one (host-only). To make the second adapter visible, I have to run a command

1
2
$ sudo dhclient
$ ifconfig

Now I got both adapters enp0s3 (NAT) and enp0s8 (host-only) visible on terminal. And now I can ping and run ssh from host (OS X) to guest (Ubuntu server).

In order to make it permanent, we need to edit /etc/network/interfaces with the following lines

1
2
3
# The second network interface
auto enp0s8
iface enp0s8 inet dhcp

Then restart the network service by running

1
$ sudo /etc/init.d/networking restart

That’s my note for now and thanks for reading.

Mono Multiple Application on a Virtual Host

| Comments

On my previous post I wrote how to configure application virtual host. We can have multiple application in a virtual host like multiple application in a web site on IIS. To do that, the steps are the same as I did on my previous post. Let’s say we have a scenario, having a site config as the sample on previous article, an application port 99, default document root /var/www/vhosts/defaultsite/root. The detail virtual host config as follow

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
<VirtualHost *:99>
    ServerAdmin admin@test.com
    ServerName  neutro.local
    ServerAlias neutrofoton.com *.neutrofoton.com

    MonoServerPath neutro.local "/usr/bin/mod-mono-server4"
    MonoDebug neutro.local true
    MonoSetEnv neutro.local MONO_IOMAP=all
    MonoApplications neutro.local "/:/var/www/vhosts/defaultsite/root"

    MonoAutoApplication disabled
    AddHandler  mono    .aspx .ascx .asax .ashx .config .cs .asmx .axd

    DocumentRoot    /var/www/vhosts/defaultsite/root
    DirectoryIndex  Default.aspx index.aspx index.html

    <Location "/">
      Allow from all
      Order allow,deny
    MonoSetServerAlias neutro.local
      SetHandler mono
      SetOutputFilter DEFLATE
      SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png)$" no-gzip dont-vary
    </Location>

    <IfModule mod_deflate.c>
      AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript
    </IfModule>

    LogLevel    debug

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

The steps to enable site config is the same as privious post. To make virtual host have multiple applications, we have to modify the site config file as follow. In this sample, we are going to add 2 applications to this virtual host

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
<VirtualHost *:99>
    ServerAdmin admin@test.com
    ServerName  neutro.local
    ServerAlias neutrofoton.com *.neutrofoton.com

    MonoServerPath neutro.local "/usr/bin/mod-mono-server4"
    MonoDebug neutro.local true
    MonoSetEnv neutro.local MONO_IOMAP=all
    MonoApplications neutro.local "/:/var/www/vhosts/defaultsite/root"

    MonoAutoApplication disabled
    AddHandler  mono    .aspx .ascx .asax .ashx .config .cs .asmx .axd

    DocumentRoot    /var/www/vhosts/defaultsite/root
    DirectoryIndex  Default.aspx index.aspx index.html

    <Location "/">
      Allow from all
      Order allow,deny
    MonoSetServerAlias neutro.local
      SetHandler mono
      SetOutputFilter DEFLATE
      SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png)$" no-gzip dont-vary
    </Location>

    Alias   /project1  "/home/neutro/Workspace/dotnet/project1"
    MonoApplications project1 "/project1:/home/neutro/Workspace/dotnet/project1"
    MonoServerPath project1 "/usr/bin/mod-mono-server4"
    <Location "/project1">
      Allow from all
      Order allow,deny
      MonoSetServerAlias project1
      SetHandler mono
      SetOutputFilter DEFLATE
      SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png)$" no-gzip dont-vary
      Require all granted
    </Location>

    Alias   /project2  "/home/neutro/Workspace/dotnet/project2"
    MonoApplications project2 "/project2:/home/neutro/Workspace/dotnet/project2"
    MonoServerPath project2 "/usr/bin/mod-mono-server4"
    <Location "/project2">
      Allow from all
      Order allow,deny
      MonoSetServerAlias project2
      SetHandler mono
      SetOutputFilter DEFLATE
      SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png)$" no-gzip dont-vary
      Require all granted
    </Location>

    <IfModule mod_deflate.c>
      AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript
    </IfModule>

    LogLevel    debug

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

In the new virtual host configuration we have:

  1. /project1, with physical application’s files in /home/neutro/Workspace/dotnet/project1
  2. /project2, with physical application’s files in /home/neutro/Workspace/dotnet/project2

Let’s assume we have a simple index.aspx file in /home/neutro/Workspace/dotnet/project1 and /home/neutro/Workspace/dotnet/project2

We need to give access to both folders and theirs file contents

1
2
3
4
5
$ find project1 -type d -exec chmod 755 {} \;
$ find project1 -type f -exec chmod 644 {} \;

$ find project2 -type d -exec chmod 755 {} \;
$ find project2 -type f -exec chmod 644 {} \;

After modifying the config file and give access to the application directories, we need to register the applications in /etc/mono-server4/debian.webapp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<apps>
   <web-application>
        <name>project1</name>
        <vpath>/project1</vpath>
        <path>/home/neutro/Workspace/dotnet/project1</path>
        <vhost>neutro.local</vhost>
    </web-application>
    <web-application>
        <name>project2</name>
        <vpath>/project2</vpath>
        <path>/home/neutro/Workspace/dotnet/project2</path>
        <vhost>neutro.local</vhost>
    </web-application>
</apps>

The final step is restart apache, and now we should be able to open in browser http://localhost:99/project1 or http://localhost:99/project2.

References

  1. http://stackoverflow.com/questions/19279286/fail-to-start-a-mono-site-with-apache2-404-error-with-mod-mono

Mono Mod_mono Apache2 on Ubuntu

| Comments

I used to write a post about install and configure Mono on OS X Mountain Lion. On this post I want to summary what I did the similar things on Ubuntu.

The details environment I use :

  1. Ubuntu 14.04 LTS
  2. Mono JIT compiler version 4.4.2
  3. Apache 2.4.7

Install Mono, Apache 2, Mod Mono

To install Mono, the first step is add package repository to our system.

1
2
3
4
5
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF

$ echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list

$ sudo apt-get update

To enable mod_mono installation on Ubuntu 13.10 or later, and Debian 8.0 and later (and their derivatives), we need to add a second repository to our system, in addition to the generic Debian/Ubuntu repository above (if you don’t use sudo, be sure to switch to root):

1
$ echo "deb http://download.mono-project.com/repo/debian wheezy-apache24-compat main" | sudo tee -a /etc/apt/sources.list.d/mono-xamarin.list

Then run package update to update and a package upgrade to upgrade existing packages to the latest available.

1
2
$ sudo apt-get update
$ sudo apt-get upgrade

To install mono, run the following command

install mono
1
$ sudo apt-get install mono-complete

If we do not have Apache 2 on our system, we need to install it first. Or we can check the existing version apache2 -v

install apache2
1
$ sudo apt-get install apache2

To be able to host ASP.NET application on apache, we need to install mod_mono. mod_mono is a module for the Apache HTTP Server that allows us to host ASP.NET pages and other assemblies on multiple platforms by using Mono.

To install Mod Mono and its dependencies run the following command

install mod_mono
1
2
$ sudo apt-get update && sudo apt-get install libapache2-mod-mono
$ apt-get install mono-apache-server4

Before going through the next step, the things than we can verify are :

  1. Ensuring Apache 2 running well at least by checking its version or start stop its service.

     $ apache2 -v
    
     $ service apache2 start
    
     $ service apache2 stop
    
  2. Checking mono version

    $ mono --version
    
  3. Ensuring we have /usr/bin/mod-mono-server4

Configuring Application Virtual Host

To configure virtual host application, the steps are

  1. Create a directory where the application physical files reside. In this sample I put my application files in /var/www/hellodotnet

    We needed to grant permissions to the login user so that the user could copy or create files to the hellodotnet directory. For our purposes we made the current user the owner of the directory

     $ chown -R -v your_user_name /var/www/
    
  2. Lets create a simple /var/www/hellodotnet/index.aspx file.

     <center>mod_mono is working:<%=System.DateTime.Now.ToString()%></center>
    
  3. Create a site configuration /etc/apache2/sites-available/hellodotnet.conf

        <VirtualHost *:81>
           ServerName hellodotnet
           ServerAdmin hello@test-apache-config.com
           DocumentRoot /var/www/hellodotnet
           MonoServerPath hellodotnet "/usr/bin/mod-mono-server4"
           MonoDebug hellodotnet true
           MonoSetEnv hellodotnet MONO_IOMAP=all
           MonoApplications hellodotnet "/:/var/www/hellodotnet"
    
           ErrorLog ${APACHE_LOG_DIR}/error.log
           CustomLog ${APACHE_LOG_DIR}/access.log combined
    
           AddHandler  mono    .aspx .ascx .asax .ashx .config .cs .asmx .axd
           <Location "/">
             Allow from all
             Order allow,deny
             MonoSetServerAlias hellodotnet
             SetHandler mono
             SetOutputFilter DEFLATE
             SetEnvIfNoCase Request_URI "\.(?:gif|jpe?g|png)$" no-gzip dont-vary
           </Location>
           <IfModule mod_deflate.c>
             AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript
           </IfModule>
         </VirtualHost>
    

    In this site I use port 81 instead of default 80.

  4. Since we use port 81, we need to register port 81 in /etc/apache2/ports.conf by simply add the following code

     Listen 81
    
  5. Enabling the site by running the following command from terminal

     $ sudo a2ensite hellodotnet.conf
    
  6. Restart apache
  7. Hit from browser : http://localhost:81 We should have the page displayed current date time.

Tips

  1. If we get the page not displayed, we can see the message on the page displayed, HTML error code, or any clue on apache logs located in /var/log/apache2

  2. If we get message access denied cannot access bin, simply change permission of the application site.

     $ find hellodotnet -type d -exec chmod 755 {} \;
     $ find hellodotnet -type f -exec chmod 644 {} \;
    
  3. If getting message could not find /etc/mono/registry, simply create the directory.

     $ sudo mkdir /etc/mono/registry
    
  4. If getting System.UnauthorizedAccessException access to the path /etc/mono/registry, give access to it as its need, for example

      $ chmod uog+rw /etc/mono/registry
    

References

  1. http://www.mono-project.com/docs/getting-started/install/linux/
  2. http://stackoverflow.com/questions/34290004/how-to-install-configure-mod-mono-on-ubuntu-14-04-3-lts
  3. http://www.bloomspire.com/blog/2015/3/9/how-to-host-aspnet-applications-on-linux-p3
  4. http://superuser.com/questions/882594/permission-denied-because-search-permissions-are-missing-on-a-component-of-the-p
  5. https://www.codementor.io/tips/7134438372/access-to-the-path-etc-mono-registry-is-denied
  6. https://retkomma.wordpress.com/2011/10/01/registry-settings-in-mono-on-linux/

VirtualBox Share Host Folder Ubuntu Guest

| Comments

VM VirtualBox is one of free popular hypervisor for x86 computer from Oracle. I use it as part of my development environment, since occasionally I need several different Operating Systems for development and software testing or deployment testing. When we work with VirtualBox we often need to share folder between host and guest operating system.

Before sharing folder, ensure we have installed Guest Addition that shipped with VirtualBox. To do that :

  1. Go to Device menu > Insert Guest CD Addition Images.
  2. If it automatically mounting and has popup dialog, just hit run otherwise we may have to manually mounting it.

I usually restart my OS guest after installing this VirtualBox Guest Addition.

The steps are :

  • Go to Devices menu > Shared Folders > Shared Folder Settings
  • Select folder path of Host to be shared to Guest OS
  • Checked Make Permanent option if we want to make it permanent

    On my sample, I shared folder from OS X Host /Volumes/MacintoshHDData/share

    Till this step is enough for Windows guest. On Ubuntu guest, it need additional steps to make the shared folder accessible in guest.

  • When we shared a Host’s folder on Ubuntu guest, VirtualBox should create a folder on /Media just like the shared folder name with sf_ prefix. In my case /Media/sf_share. If the folder does not exist, open terminal, create directory /Media/sf_share and give folder name

    mkdir /Media/sf_share
    
  • VirtualBox with Ubuntu operating system guest, it added a group called vboxsf. Before we can access the shared folder we have to be a member of the group.

    sudo add user [username] vboxsf
    

    To verify what groups are username belongs to,

    id [username]
    
  • Mount the shared folder

    sudo mount -t vboxsf share /media/sf_share
    

Now we should be able to the shared folder via Nautilus (File Manager). To make it automatic mounting, ensure we checked option automatic mounting on shared folder setting dialog.

References

  1. http://askubuntu.com/questions/456400/why-cant-i-access-a-shared-folder-from-within-my-virtualbox-machine
  2. http://www.howtogeek.com/187703/how-to-access-folders-on-your-host-machine-from-an-ubuntu-virtual-machine-in-virtualbox/

Lambda in C++

| Comments

C++11 adds a new feature called lambda expressions. This allows us to write anonymous functions inline, removing the need to write a separate function or to write a function object, and makes code easier to understand. For those who are familiar with C# lambda expression, C++ lambda expression is similar. But lambda in C++ has slightly different syntax.

C++11 Lambda Syntax
1
[capture_block](parameters) mutable exception_specification -> return_type {body}
  1. capture_block is a comma-separated list of zero or more captures, optionally beginning with a capture-default. Capture list can be passed as follows (see below for the detailed description):
    1. [a,&b] where a is captured by value and b is captured by reference.
    2. [this] captures the this pointer by value
    3. [&] captures all automatic variables odr-used in the body of the lambda by reference
    4. [=] captures all automatic variables odr-used in the body of the lambda by value
    5. [x] captures only x by value and nothing else.
    6. [] captures nothing
  2. parameters is (optional) list of parameters for the lambda expression.
  3. mutable is (optional) if variables from the enclosing scope are captured by value, a copy of those variables will become available in the body of the lambda expression. Those copies are marked as const by default, meaning the lambda body cannot change the value of those copies. If the lambda expression is marked as mutable, those copies are not const and the body can modify those local copies.
  4. exception_specification is (optional) and can be used to specify which exceptions the body of the lambda expression can throw.
  5. return_type is Return type. If not present it's implied by the function return statements (or void if it doesn't return any value)

Lambda and Direct Invoke

The following snipped code is an example of lambda expression.

example lambda and directly invoked
1
2
string result = [](const string& str) -> string {return "Hi " + str;}("neutro");
cout << result << endl;

The lambda expression above shows that it has a const string& parameter and return a string type. To execute the lambda is by placing round brackets () and put object that will be passed to inside it. The “neutro” literal string will substitute str parameter. The output of the above code is :

output
1
Hi neutro

Lambda as Variable

Pointer to a lambda expression can be stored and executed through the function pointer. C++ provides std::function which is a STL template class that provides a very convenient wrapper to a simple function, to a functor or to a lambda expression. We can also use the C++11 auto keyword to make it easier.

To make it clear the following code contains couples of various lambda expressions and store them in variables of type auto or its equivalent in std::function STL template class.

lambda as variable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
auto lambda1 = [] { cout <<"Hello lambda without parameter 1" << endl; };
lambda1();

auto lambda2 = [](void) { cout <<"Hello lambda without parameter 2" << endl; };
lambda2();

//auto lambda3 = [](void) -> void { cout <<"Hello lambda without parameter 2" << endl; };
function<void()> lambda3 = [](void) -> void { cout <<"Hello lambda without parameter 2" << endl; };
lambda3();

//auto lambda4 = [](const string& str) -> string {return "Hello from " + str;};
function<string(const string&)> lambda4 = [](const string& str) -> string {return "Hello from " + str;};

string result = lambda4("neutro");

cout << result << endl;

The snipped code above shows how lambda expressions stored in variable of auto type or theirs equivalent in std::function type and how to invoke the lambda. Here is a good article about std::function.

Lambda Capture Block

Lambda Capture Block basically describes how we want to capture variables from the enclosing scope. Capturing a variable means that the variable becomes available inside the body of the lambda. The detail variant of capture block has been described on previous section. The following code shows various scenario how to play with capture block.

lambda capture block
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
int variableA = 1;
int variableB = 1;
int variableC = 1;

cout << "Init Values : "<<endl;
cout << "variableA : "<<variableA <<endl;
cout << "variableB : "<<variableB <<endl;
cout << "variableC : "<<variableC <<endl;

cout << endl;
//--------------------------------------
cout << "---## lamda 1 ##---"<<endl;
auto lambda1 = [=](int param)-> int     //==> [=] lambda has default access to variable is by value
            {
                param = param * 2;

                cout << "param inside lambda1 : "<<param << endl;
                return param;
            };

lambda1(variableA);
cout << "After lamda1, variableA : " <<variableA <<endl;

cout<<endl;

//--------------------------------------------
cout << "---## lamda 2 ##---"<<endl;
auto lambda2 = [&](int param) -> int      //==> [&] lambda has default access to variable is by reference
            {
                param = param * 2;
                variableB = variableB * 2;

                cout << "param inside lambda2 : "<<param << endl;
                cout << "variableB inside lambda2 : "<<variableB << endl;

                return param;
            };

lambda2(variableA);
cout << "After lamda2, variableA : " <<variableA <<endl;
cout << "After lamda2, variableB : " <<variableB <<endl;

cout<<endl;

//-------------------------------------
cout << "---## lamda 3 ##---"<<endl;
auto lambda3 = [&](int* param) -> int
{
    *param = (*param) * 2;
    variableB = variableB * 2;

    cout << "param inside lambda3 : "<<*param << endl;
    cout << "variableB inside lambda3 : "<<variableB << endl;

    return *param;
};

int result3 = lambda3(&variableA);
cout << "After lamda3, result3 : " <<result3 <<endl;
cout << "After lamda3, variableA : " <<variableA <<endl;
cout << "After lamda3, variableB : " <<variableB <<endl;

cout<<endl;


//--------------------------------
cout << "---## lamda 4 ##---"<<endl;
auto lambda4 = [=, &variableB, &variableC](int param) -> int //==> [=, &variableB, &variableC] captures by value by default,
                                             // except variables variableB and variableC, which are captured by reference.
{
    param = (param) * 2;
    variableB = variableB * 2;
    variableC = variableC * 2;

    cout << "param inside lambda4 : "<<param << endl;
    cout << "variableB inside lambda4 : "<<variableB << endl;
    cout << "variableC inside lambda4 : "<<variableC << endl;

    return param;
};

lambda4(variableA);

cout << "After lamda4, variableA : " <<variableA <<endl;
cout << "After lamda4, variableB : " <<variableB <<endl;
cout << "After lamda4, variableC : " <<variableC <<endl;

cout << endl;

//--------------------------------
cout << "---## lamda 5 ##---"<<endl;
auto lambda5 = [variableC](int param) mutable -> int //==> [variableC] captures only variableC by value and nothing else.
{
    param = (param) * 2;

    variableC = variableC * 2; //should mark as mutable lambda, since Cannot assign to a variable captured by copy in a non-mutable lambda
    //variableB = variableB * 2; //ERROR : variableB not captured, since only capture specific variable that's variableC

    ///
    cout << "param inside lambda5 : "<<param << endl;
    cout << "variableC inside lambda5 : "<<variableC << endl;

    return param;
};

lambda5(variableA);

cout << "After lamda5, variableA : " <<variableA <<endl;
cout << "After lamda5, variableC : " <<variableC <<endl;

The output of the sample code is :

output
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
Init Values :
variableA : 1
variableB : 1
variableC : 1

---## lamda 1 ##---
param inside lambda1 : 2
After lamda1, variableA : 1

---## lamda 2 ##---
param inside lambda2 : 2
variableB inside lambda2 : 2
After lamda2, variableA : 1
After lamda2, variableB : 2

---## lamda 3 ##---
param inside lambda3 : 2
variableB inside lambda3 : 4
After lamda3, result3 : 2
After lamda3, variableA : 2
After lamda3, variableB : 4

---## lamda 4 ##---
param inside lambda4 : 4
variableB inside lambda4 : 8
variableC inside lambda4 : 2
After lamda4, variableA : 2
After lamda4, variableB : 8
After lamda4, variableC : 2

---## lamda 5 ##---
param inside lambda5 : 4
variableC inside lambda5 : 4
After lamda5, variableA : 2
After lamda5, variableC : 2

Reference

  1. Wrox Professional C++
  2. http://en.cppreference.com/w/cpp/language/lambda
  3. https://oopscenities.net/2012/02/24/c11-stdfunction-and-stdbind/
  4. http://www.drdobbs.com/cpp/lambdas-in-c11/240168241?pgno=1

Configure Boost (C++ Libraries) on Xcode, Code::Blocks and Visual Studio

| Comments

Boost is a set of libraries for the C++ programming language that provide support for tasks and structures such as linear algebra, pseudorandom number generation, multithreading, image processing, regular expressions, and unit testing. It contains over eighty individual libraries.[2]

The other interesting points of Boost are :

  1. Open source
  2. Cross platform
  3. Complement to STL rather than a replacement
  4. Many of Boost developers are on the C++ standard committee
  5. Well documented
  6. Most of the Boost libraries are licensed under the Boost Software License, designed to allow Boost to be used with both free and proprietary software projects

Installation Boost

Before jumping into steps of configuring Boost on various IDE, let’s begin with Boost installation. To be noted that on this post I run Xcode on OS X, Code::Blocks on Linux (Ubuntu) and Visual Studio on Windows. The detail environments I use are :

  1. OS X 10.11.4 El Capitan
  2. Ubuntu 14.04.4 LTS
  3. Xcode Version 7.2
  4. Code::Blocks 13.12, gcc 4.8.4
  5. Visual Studio 2013
  6. Boost 1.60.0

OS X and Linux (Ubuntu)

There are several ways of Boost installation. Instead of build from source code, we can use package manager such as MacPorts, Homebrew, Advance Package Tool, etc. In this post we will build Boost from source code. The installation steps (from source code) on OS X and Ubuntu are the similar. To make it consistent, I use the same installation path for OS X and Ubuntu that is /usr/local/boost_1_60_0. You can use different path if you want. The steps are :

  1. Download boost library from Boost website
  2. Extract it.
  3. Open terminal, navigate to the extracted directory
  4. Create directory on /usr/local/boost_1_60_0, and ensure IDE has access to the directory. On my case I don't need this step on OS X, but on ubuntu it does.
    1
    2
    
    sudo mkdir /usr/local/boost_1_60_0
    sudo chmod 777 -r boost_1_60_0
    
  5. Run command :
    1
    2
    
    ./bootstrap.sh --prefix=/usr/local/boost_1_60_0
    ./b2 install
    
    This last step quite take time. So you can have coffee while waiting for it :)

Once the installation finish, we should have generated directory. They are /usr/local/boost_1_60_0/include contains header files and /usr/local/boost_1_60_0/lib contains libraries.

Windows

The Boost installation step on Windows is also similar to the installation step on OS X and Ubuntu. The steps are :

  1. Download boost library from Boost website
  2. Extract it to C:\\boost_1_60_0
  3. Open Visual Studio command prompt. I use Visual Studio 2013 x86 Native Tools Command Prompt native tool (I have not test using default Windows Command Prompt)
    1
    2
    3
    
    C:\> cd C:\boost_1_60_0
    C:\boost_1_60_0> bootstrap.bat
    C:\boost_1_60_0> .\b2
    
    As on OS X and Ubuntu, the last step quite take time.

Configure Boost on IDE(s)

Before create C++ projects on various IDE, let’s create a simple C++ hello world code that use Boost libraries. To simplify the test, I grab sample code from here

Hello World
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
#include <iostream>
#include <fstream>
using namespace std;

#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/stream.hpp>
using namespace boost;
using namespace boost::iostreams;

int main(int argc, const char * argv[]) {

    typedef tee_device<ostream, ofstream> TeeDevice;
    typedef stream<TeeDevice> TeeStream;

    ofstream ofs("/Users/neutro/Workspace/cpp/sample.txt");

    TeeDevice my_tee(cout, ofs);
    TeeStream my_split(my_tee);

    my_split << "Hello, World!\n";

    my_split.flush();
    my_split.close();

    return 0;
}

The snipped code above just print text and write it to a text file. We just want to ensure the IDE’s compiler can compile and build the code that includes Boost libraries.

  • Xcode

    To include Boost libraries on Xcode project :
    1. Select Xcode project > Build Setting
    2. Add /usr/local/boost_1_60_0/include/ to the Header Search Paths
    3. Add /usr/local/boost_1_60_0/lib/ to the Library Search Paths
  • Code::Blocks

    To include Boost libraries on Code::Blocks project :
    1. Right Click on Code::Blocks project > Build Option
    2. Select Compiler tab, add /usr/local/boost_1_60_0/include/
    3. Select Linker tab, add /usr/local/boost_1_60_0/lib/
  • Visual Studio

    To include Boost libraries on Visual C++ project :
    1. Right Click on VC++ project > Properties
    2. Select VC++ Directories on the left pane
    3. Add C:\boost_1_60_0 on Include Directories item
    4. Add C:\boost_1_60_0\stage\lib on Include Directories item
    5. Click OK to close the dialog

The last is rebuild the above code on selected IDE. We should not got any errors once the IDE can detect the Boost directory path.

The sample of this article can be downloaded here

Reference

  1. http://www.boost.org/
  2. Wikipedia