Search in the blog

вівторок, 27 квітня 2010 р.

CMake + VC++2010

There is now the bug in CMake 2.8.1 with Visual Studio 2010 Express - compiler checks doesn't work. Here is http://www.itk.org/Bug/view.php?id=10539 patch for this bug.

вівторок, 20 квітня 2010 р.

Time convertions with daylight saving

I've found how to convert time from UTC to local time with daylight saving correction:
1. Use mktime() to create time from string(or some thing else)
2. get time from gmtime() and localtime()
3. calculate difference between time to get timezone offset (or use _get_timezone)
4. use tm::tm_isdst to determine apply or not daylight saving
5. use _get_daylight() to get value in hours of daylight correction.

понеділок, 19 квітня 2010 р.

Online compiler

Here is codepad cool on-line compiler

неділя, 18 квітня 2010 р.

Perfect forwarding full example

Here is an example of how to use rvalue references for forwarding:

#include <functional>
#include <iostream>
#include <memory>

class V
{
public:
    explicit V(int x)
        :x(x)
    {
            std::cout << "V()\n";
    }

    int x;
protected:
    V(const V&){}
    V& operator=(const V&){}
};

class A
{
public:
    A(V& v)
    {
        std::cout << "A(V&) x = " << v.x << "\n";
    }
};

template<typename T, typename Arg> 
std::shared_ptr<T> factory(Arg arg)
{ 
  return std::shared_ptr<T>(new T(arg));
} 

template<typename T, typename Arg> 
std::shared_ptr<T> factory2(Arg&& arg)
{ 
    // you can't use std::move for forwarding - compiler error
    return std::shared_ptr<T>(new T(std::forward<V>(arg)));
} 

int main(int argc, char* argv[])
{  
    V v(1);

    A a(v);

    // compiler error
    //std::shared_ptr<A> a1 = factory<A>(v);

    std::shared_ptr<A> a1 = factory2<A>(v);

    return 0;
}

Practical example of Rvalue references and move semantics

Here is simple example how to use move semantics to optimize you code - you can override + operator to reduce constructor numbers:
#include <functional>
#include <iostream>

class A
{
public:
    A(int x)
        :x(x)
    {
        std::cout << "A(int x)\n";
    }

    A(const A& a)
        :x(a.x)
    {        
        std::cout << "A(const A&)\n";
    }

    A& operator=(const A& a)
    {
        x = a.x;
        return *this;
    }

    A operator+(const A& a)
    {
        return A(x + a.x);
    }

private:
    int x;
};


class B
{
public:
    B(int x)
        :x(x)
    {
        std::cout << "B(int x)\n";
    }

    B(const B& b)
        :x(b.x)
    {        
        std::cout << "B(const B&)\n";
    }

    B(B&& b)
        :x(std::move(b.x))
    {        
        std::cout << "B(B&&)\n";
    }

    B& operator=(const B& b)
    {
        x = b.x;
        return *this;
    }

    B& operator=(B&& b)
    {
        x = std::move(b.x);
        return *this;
    }

    B operator+(const B& b)
    {
        return B(x + b.x);
    }

    B&& operator+(B&& b)
    {
        b.x += x;
        return std::move(b);
    }

private:
    int x;
};
 
int main(int argc, char* argv[])
{
    A a1(5);
    A a2 = a1 + 2 + 3;

    B b1(5);
    B b2 = b1 + 2 + 3;
    return 0;
}

пʼятниця, 16 квітня 2010 р.

Simple unit test framework for C++

I want to create very simple unit test framework for C++ which can be used with Visual Studio. I mean that it must have some integration to IDE. When i searched  for some existent frameworks i didn't find anything useful and open source. Also i want this framework should be very lightweight, and test creation should take very little time, because instead test creation doesn't have sense.
So here is first version, it use new features from C++0x, and was created in Visual Studio2010 Express.It produce output to standard Output window, and you can click on failed assertion message to move you code editor to required code line.

Test.h:

#pragma once 

#include <sstream>

#define CHECK(v) self->Assert(##v, L#v, __FILE__, __LINE__);

#define CHECK_EQUALS(v1, v2) self->AssertEquals(##v1, ##v2, L#v1,  L#v2, __FILE__, __LINE__);

#define CHECK_NOT_EQUALS(v1, v2) self->AssertNotEquals(##v1, ##v2, L#v1,  L#v2, __FILE__, __LINE__);

#define TEST(name) void name(testengine::Test* self)

namespace testengine
{

class Test
{
public:
    Test() : done(true) {self = this;}
    virtual ~Test(){}
    virtual void Setup(){}
    virtual void TearDown(){}
    virtual void Run() = 0;   

    void Assert(bool rez, const std::wstring& msg, const std::string& fileName, size_t line)
    {
        if (!rez)
        {
            std::wstringstream buf;        
            buf << fileName.c_str() << L"(" << line << ") : Assertation failed : " << msg.c_str() << std::endl;
            report += buf.str();
            done = false;
        }    
    }

    template <class T1, class T2>
    void AssertEquals(T1 v1, T2 v2, const std::wstring& msg1, const std::wstring& msg2, const std::string& fileName, size_t line)
    {
        std::wstringstream buf;
        buf << msg1 << L" == " << msg2;
        Assert(v1 == v2, buf.str(), fileName, line);
    }

    template <class T1, class T2>
    void AssertNotEquals(T1 v1, T2 v2, const std::wstring& msg1, const std::wstring& msg2, const std::string& fileName, size_t line)
    {
        std::wstringstream buf;
        buf << msg1 << L" != " << msg2;
        Assert(v1 != v2, buf.str(), fileName, line);
    }

    const std::wstring GetReport() {return report;}

    bool IsDone() {return done;}
protected:
    Test* self;
private:    
    std::wstring report;
    bool done;
};

}

TestExecuter.h:

#pragma once 

#include "Test.h"

#include <memory>
#include <vector>
#include <string>
#include <tuple>
#include <sstream>
#include <functional>

#include <windows.h>

namespace testengine
{

typedef std::function<void(Test*)> TestFunction;

class SingleFunctionTest : public Test
{
public:
    SingleFunctionTest(TestFunction func) : func(func){}
    virtual void Run()
    {
        func(this);
    }

private:
    TestFunction func;
};

class TestExecuter
{
public:

    void AddTest(TestFunction func, const std::wstring& name)
    {
        tests.push_back(std::make_tuple(name, new SingleFunctionTest(func))); 
    }

    template<class T>
    void AddTest(const std::wstring& name)
    {
        tests.push_back(std::make_tuple(name, new T)); 
    }

    void RunTests()
    {
        OutputDebugStringW(L"=============================================================================\n");
        OutputDebugStringW(L"Start running tests :\n");
        auto i = tests.begin(), e = tests.end();
        size_t passed = 0;
        size_t failed = 0;
        for (;i != e; ++i)
        {
            OutputDebugStringW(L"-----------------------------------------------------------------------------\n");
            bool go = true;
            std::wstringstream buf;
            buf << std::get<0>(*i);
            try
            {
                std::get<1>(*i)->Setup();               
            }
            catch(...)
            {
                buf << L" - Fails : Unhandled exception while Setup\n";
                OutputDebugStringW(buf.str().c_str());
                go = false;
                ++failed;
            }

            if (go)
            {
                try
                {
                    std::get<1>(*i)->Run();               
                }
                catch(...)
                {
                    buf << L" - Fails : Unhandled exception while Run\n";
                    OutputDebugStringW(buf.str().c_str());
                    go = false;
                    ++failed;
                }
            }

            if (go)
            {               
                try
                {
                    std::get<1>(*i)->TearDown();               
                }
                catch(...)
                {
                    buf << L" - Fails : \n";
                    buf << std::get<1>(*i)->GetReport();
                    buf << L"Unhandled exception while TearDown\n";
                    OutputDebugStringW(buf.str().c_str());
                    go = false;
                    ++failed;
                }
            }

            if (go)
            {
                if (!std::get<1>(*i) ->IsDone())
                {
                    buf << L" - Fails : \n" << std::get<1>(*i)->GetReport();
                    OutputDebugStringW(buf.str().c_str());
                    ++failed;
                }
                else
                {
                    buf << L" - OK\n";
                    OutputDebugStringW(buf.str().c_str());
                    ++passed;
                }    
            }
        }
        OutputDebugStringW(L"-----------------------------------------------------------------------------\n");
        std::wstringstream buf;
        buf << L"All tests finished : passed = " << passed << L" failed = " << failed << std::endl;
        OutputDebugStringW(buf.str().c_str());
        OutputDebugStringW(L"=============================================================================\n");
    }

private:
    std::vector<std::tuple<std::wstring, std::shared_ptr<Test> > > tests;
};

}

main.cpp:

#include "TestEngine\TestExecuter.h"

class MyTest1 : public testengine::Test
{
public:
    virtual void Run()
    {
        CHECK(1 == 0);
    }
};

class MyTest2 : public testengine::Test
{
public:
    virtual void Run()
    {
        CHECK(1 == 1);
    }
};

class MyTest3 : public testengine::Test
{
public:
    virtual void Run()
    {
        CHECK_EQUALS(1, 2);
    }
};

class MyTest4 : public testengine::Test
{
public:
    virtual void TearDown()
    {
        throw 1;
    }

    virtual void Run()
    {
        CHECK_EQUALS(3, 4);
    }
};


class MyTest5 : public testengine::Test
{
public:

    virtual void Setup()
    {
        throw 1;
    }


    virtual void TearDown()
    {
        throw 1;
    }

    virtual void Run()
    {
        CHECK_EQUALS(3, 4);
    }
};


class MyTest6 : public testengine::Test
{
public:

    virtual void TearDown()
    {
        throw 1;
    }

    virtual void Run()
    {
        throw 1;
        CHECK_EQUALS(3, 4);
    }
};

TEST(MyTest7)
{
    CHECK_NOT_EQUALS(4, 4);
}

int main(int argc, char* argv[])
{
    testengine::TestExecuter testExec;

    testExec.AddTest<MyTest1>(L"MyTest1");
    testExec.AddTest<MyTest2>(L"MyTest2");
    testExec.AddTest<MyTest3>(L"MyTest3");
    testExec.AddTest<MyTest4>(L"MyTest4");
    testExec.AddTest<MyTest5>(L"MyTest5");
    testExec.AddTest<MyTest6>(L"MyTest6");
    testExec.AddTest(MyTest7, L"MyTest7");

    testExec.RunTests();
    
    return 0;
}