LAZR.PW
Stuff I'm working on.

Sunday, 3 February 2013

C++11


I have begun to adopt the C++11 standard into my default C++ programming style, as the new features provide the ability to write cleaner, simpler and safer code. Here is some simple examples of some of the features added in C++11 that I've found uses for. This code may not be very efficient as it is intended for demonstration of new key concepts.

Main features I find useful:
  • Lambda and auto:
#include <iostream>
#include <string>
#include <sstream>

int perform(int operation(int a, int b), int x, int y)
{ // Pass function as parameter and apply it to the other inputs.
    return operation(x, y);
}

int main()
{
    std::cout << perform([](int a, int b){ return a + b; }, 5, 4) << std::endl;
    // Defines an addition operation as one of the methods parameters.

    int i = 5;

    auto f = [&i] (std::string text) ->std::string
    { // Let the Lambda use the local variable i by reference.
        std::stringstream ss; ss << text << " " << i; return ss.str();
    };

    std::cout << f("hello");

    std::cin.get();
    return 0;
}
  • Smart pointers:
#include <iostream>
#include <memory>

struct MyObject
{
    MyObject(int id) : id(id)
    {
        std::cout << "Object created " << id << std::endl;
    }

    void doSomething()
    {
        std::cout << "Doing something " << id << std::endl;
    }

    ~MyObject()
    {
        std::cout << "Deleting object " << id << std::endl;
    }
};

int main()
{
    std::unique_ptr<MyObject> p1(new MyObject(1));

    p1->doSomething(); // Invokes p1's doSomething method.

    if(p1)
    {
        std::unique_ptr<MyObject> p2(new MyObject(2)); // Creates second object with id of 2.

        p2->doSomething(); // Invokes p2's doSomething method.

    } // p2 goes out of scope and destroys the object.

    std::cout << "When you press enter the program will end after" << std::endl
                        << "p1 goes out of scope and destroys the object.";
    std::cin.get();
    // p1 goes out of scope and destroys the object.
    return 0;
}
  • Chrono (clocks and durations):
#include <iostream>
#include <chrono>

typedef std::chrono::milliseconds millis;
typedef std::chrono::seconds secs;
typedef std::chrono::high_resolution_clock high_res_clock;

int main()
{
    auto start = std::chrono::high_resolution_clock::now();
 
    secs sec(25);
 
    std::cout << "Seconds: " << sec.count() << std::endl;

    std::cout << "Milliseconds: " << std::chrono::duration_cast<millis>(sec).count();
    /* The duration cast uses the ratio between the durations when converting.
     * If you cast 1500 milliseconds to seconds you will lose data (obviously).
     */
    std::cin.get();
    return 0;
}
  • New for loop syntax (Java-like) and Lambda with for_each:
#include <algorithm>
#include <vector>
#include <iostream>

int main()
{
    std::vector<int> vec;
 
    for(int i(1); i <= 5; i++)
    {
        vec.push_back(i);
    }
    std::cout << std::endl << "Original Values:" << std::endl;

    for(int i : vec)
    {
        std::cout << i << std::endl;
    }
    std::for_each(vec.begin(), vec.end(), [](int &v){v *= 2;});
    /* The lambda replaces the need to create a function just for the use of the for each.
     * Lambdas also provide the ability to write functions in the scope and give them a local
     * identifier using the auto type.
     */
    auto f = [](const int& i){std::cout << i << std::endl;};

    std::cout << std::endl << "Doubled Values:" << std::endl;
    /* The combination of a range based for loop and locally identified lambdas makes for
    * easily readable, and therefore easily maintainable code*/
    for(int i : vec)
    {
        f(i);
    }
    std::cin.get();
    return 0;
}
The new for loop syntax is just like the alternate Java syntax, it's useful as it eliminates the possibility of out of bounds issues, as it is taken care of and abstracted away.

Lambda is useful for times where you need a function in one area and don't want to have to create a whole separate function elsewhere that you are never going to use anywhere else. They are also useful for functions that take functions as a parameter, as you can see I am getting each variable through an int& and doubling it then reassigning to itself.

Saturday, 2 February 2013

CSV(or any specified char separator) to a vector of strings

#include <string>  
#include <vector>  
#include <sstream>  
  
void splitStr(const std::string &source, char key, std::vector<std::string>& result)  
{  
    std::stringstream ss(source);  
  
    while(ss.good())  
    {  
        std::string substr;  
        std::getline(ss, substr, key); // Get substring separated by delimiter key  
        result.push_back(substr);  
    }  
} 
This will basically loop through the string splitting it by a specified key and push each string into a vector of strings. With C++11 it may be just as efficient to create the vector inside the function and just return it; as vectors utilize R-value referencing in their move constructor (A modified copy constructor for a shallow copy that moves a reference to the data rather than the data itself).