CAUTION!

CAUTION! DANGER ZONE ahead. Beware of misinformation on the open internet. Contents of the site are mere opinions and are not always facts!

Saturday, December 13, 2014

Hands-on with QT

A record of solutions to issues that were resolved to develop a C++ QT windows desktop application. Only those that are not answered by search engines!

Development environment:
Processor: x64
OS: Windows 8.1 Pro
QT: 5.1.1

Work In Progress:

1. Application exited with code -1073741515
Background: application did not start and console reports the error code.
RCA: Run the application with debugger attached. Missing DLL reported in the error dialog. Navigate to the configured output folder. Run the exe. Windows explorer reports QTCored.dll missing.
Fix: Configure the environment variable "path" with the path to QT bin folder which contains the dependent debug libraries.

1. Application exited with code 0
Background: application did not start and console reports the error code.
RCA: No cause identified for the bug even under debug mode. The application exits even before the first line of main gets executed. Create a sample GUI application identical to the application not working (QMainWindow based). Check that it runs. Add required event listeners and check it still runs. Add cpp and h files iteratively and check it runs. Stop when it doesn't run anymore! On careful examination, there is another main present written for test which is not disabled by the TEST macro!!!
RC: Multiple Main found. Otherwise, trace the buggy code that terminates the application from the correct main.
Fix: Disable the test macro.



Saturday, October 25, 2014

Overloading functions with same signatures

The static polymorphism in C++ allows multiple functions with the same name offer different functionalities via function overloading. The overloaded functions vary in their signature and the compiler would resolve the function calls based on the parameters passed to the function. It is not possible to overload functions with same parameters. Sometimes, it is desirable to overload functions based only on the return type. One such scenario is shown below, where the data needs to be de-serialized into C++ POD types. The functions with same name and signature cause ambiguity in calling.

int get(Json::Value);
std::string get(Json::Value);

And thus the functions should either be renamed or emulate overloading. The disadvantage of renaming the functions to distinct names is that they cannot be called from other template functions or additional mechanism should be implemented by the template functions to determine the template parameter type and then call the suitable function.

int getInt(Json::Value);
std::string getString(Json::Value);

template<typename T>
struct POD
{
    T value;
    Json::Value operator=(Json::Value v)
    {
         value = ; //determine the type of T and call the suitable function for assignment 
         return v;
    }
};

Taking advantage of the type casting, it can be achieved by overloading the conversion/ type-cast operators. The casting can be either implicit or explicit.

struct Conv
{
    Json::Value val;

    Conv(Json::Value v) :val(v) { }
    operator std::string() { /*Convert and Return*/}
    operator int() { /*Convert and Return*/ }
};

int x = Conv(jsonVal); // create an anonymous object and convert

The overloading can also be achieved by template specialization and calling the required function explicitly.

namespace Conv
{
    template<typename T>
    T get(Json::Value); // linker complains for types not specialised
    template<>
    int get(Json::Value v)
    {
        /* Convert and Return*/
    }

    template<>
    std::string get(Json::Value v)
    {
        /* Convert and Return*/
    }
}

template<typename T>
struct POD
{
    T value;

    Json::Value operator=(Json::Value v)
    {
         value = Conv::get<T>(v);
         return v;
    }
};

Wednesday, September 17, 2014

Singleton pattern by inheritance

Singleton pattern is one of the fundamental design patterns used in OOP. The traditional way of implementing this is by making the constructor's private and providing a static member that can create the instance - Meyers singleton implementation. This is an implementation of the singleton pattern utility in c++ by inheritance, which imposes the pattern on the classes that derive from it. Any attempt to create the singleton class causes compilation error.

The implementation can be found here. It needs C++11 support for smart pointers , thread safety and variadic templates.

A single instance of the class is created and shared using smart pointers with the public static member. The singleton candidate is made non copyable so that multiple instances don't exist on copy by making the copy constructors private. In order to avoid the single state of the singleton candidate throughout the life time of the application, a weak pointer is used to store the instance. A shared pointer can be used if a global instance is desired. A tag is created for every singleton candidate which is accessible only to the singleton candidate, which prevents its creation from outside the utility class. It provides support for any signature of the singleton candidate constructor with the help of variadic templates.

The singleton candidate is expected to inherit from the utility class publicly and accept the tag as the first parameter in its constructors, which can be passed only by the utility class.

A sample singleton candidate is shown below.

#include<MySingleton.hpp>

class CSingletonCandidate : public CSingleton<CSingletonCandidate>
{
    private:
    int val;

    public:
    CSingletonCandidate(CSingletonTag<CSingletonCandidate>::TYPE tag, int v) : 
                        CSingleton(tag), 
                        val(v)
    {

    }
};

CSingletonCandidate::Type_T singleInstance = CSingletonCandidate::GetInstance<>(1);


This pattern is considered evil in some of the use cases and should be used cautiously. Singleton classes can also be used as a base class and the implementation of singletons should preserve the pattern even after being inherited and optionally allow multiple instances of the derived classes. This implementation  is strictly singleton and cannot be base class. It can be tweaked to support derived class in which case the base class/ singleton candidate is not strictly singleton and the derived classes can create its instances. The derived classes can further be singletons by using the utility class.

The caveat is that the singleton candidate itself can create loopholes to tarnish the singleton pattern.

Wednesday, August 27, 2014

Unsigned int overflow in decrementing loops

A case study of interger overflow's impact on iterators. when an unsigned integer is used in decrementing "for" loops. The loop unexpectedly iterates indefinitely if the loop had to terminate when the value becomes lesser than 0.

for(unsigned int i = length; i >= 0; --i)
{
    //...
}

Since an unsigned integer is used, decrementing the variable to lesser than 0 will roll the value back to the
MAXIMUM_VALUE
that can be stored in the variable (depending on its size, usually 4 bytes - on 32 or 64 bit Windows), which is always >=0.

One possible solution is to terminate the loop when the value becomes greater than the initial assigned value or equal to the
MAXIMUM_VALUE
.

for(unsigned int i = length; i <= length; --i)
{
    //...
}

for(unsigned int i = length; i != MAXIMUM_VALUE; --i)
{
    //...
}

Another solution would be to reserve 0 for the terminating condition. Note that the length should not be equal to
MAXIMUM_VALUE
. Thus, a variable can be used to iterate a maximum count of
MAXIMUM_VALUE
.
for(unsigned int i = length + 1; i > 0; --i)
{
    //Use i-1 ...
}
But, why use unsigned int at all? a signed integer does not have this problem. Because, unsigned integer have wider positive values range than the signed integer.

positive value range for signed integer: 0 to std::numeric_limits<signed  int >::max()
positive value range for unsigned integer: 0 to std::numeric_limits<unsigned  int >::max()

where, std::numeric_limits<signed  int >::max() std::numeric_limits<unsigned  int >::max()

Wednesday, August 6, 2014

Is C++ truly cross-platform?

Is C++ truly cross-platform?

The answer is yes! the C++ language standard is. Code written to comply with this standard is cross platform.

Porting the code to various platforms gets difficult when non standard code is written to accomplish more useful tasks.

1. We need OS APIs for Multi-Threading, Networking, GUI etc. There are several cross platform (common interface with different implementations) libraries like Boost, QT, libcurl, cpp-netlib etc that provide the same OS specific functionality on different platforms.

2. The code should be compiled for different platforms and we need compilers that supports the same version of C++ on different platforms. Compiler specific types or directives shouldn't be used.

3. Non standard use cases like character encoding and Endianness should be considered.

Non standard code can anymore be avoided with the introduction of new versions of C++, C++11 and C++14; and cross platform compilers, Clang.

Thus, writing truly cross platform C++ should be a piece of  ðŸŽ‚!!!

Sunday, July 27, 2014

Why C++?

Among several programming languages like C, Objective-C, C++, java, C#, ECMAScript/ JavaScript, ActionScript, Lua, Swift, Go, Erlang, Why C++?

Every language is good or is evolving to be good at what it was designed for! These are the advantages of using C++.

C++ is a mainstream language used for a wide range of purposes like embedded systems/ Operating Systems, server development, gaming, desktop/ mobile applications etc.

C++ is a high performance language. The code is directly compiled to a machine executable unlike coffee based languages which are executed by a runtime environment after bytecode interpretation and JIT compilation. say, CLR for .NET languages or JRE for Java. The scripting languages are interpreted by a runtime environment. say, a web browser interprets JavaScript. C++ is used for high performance and maintainable applications. It does not have garbage collection overhead and thus is faster than its counterpart. It can be integrated with other languages using SWIG, JNI, NaN, CLS (Common Language Specification in a managed environment) etc.

C++ is a multi paradigm language. OOP, Generic, object functional paradigm for scalable application development. C is a high performance language but does not support OOP and is used when scalability/ maintenance is not a priority like device driver development.

C++ is portable across various platforms! Various compilers like GCC, intel compiler, visual studio, Clang etc are available for different platforms to compile c++ code. Several platform abstraction libraries are available for interoperability. C++ needs to be compiled for every platform unlike coffee based languages (Java!).

Generic programming, OOP, programming idioms and other robust features like smart pointers, r-value references, lambda's etc introduced in C++11 and C++14 makes C++ more powerful and easy to use.