• HOME
  • ABOUT US
  • SERVICES
  • PORTFOLIO
  • BLOG
Connection Quest Connection Quest
  • HOME
  • ABOUT US
  • SERVICES
  • PORTFOLIO
  • BLOG
Connection Quest

Be generic

Home / Clean C++ / Be generic

Be generic

By Marko Jovic inClean C++

Because C++ is a strongly-typed language, there are situations where we are required to duplicate code more than we would like to. Consider this contrived example:

int sum (int x, int y) {
	return x + y;
}

float sum (float x, float y) {
	return x + y;
}

Ok, so we need to implement integer and floating-point number addition. Because C++ requires us to specify the type of all parameters, these will obviously need to be two different functions. At least function overloading enables us to reuse the sum function in different use cases. But if you look inside the functions, it is apparent that they are completely identical. Furthermore, if we decide to support more types (double, char, user-defined types…), we’ll have got a lot of similar functions unnecessarily cluttering up our code.

The solution? Use templates.

template <typename T> 
T sum(T x, T y) {
	return x + y;
}

As you can see, this is a lot better. This function template can be used for every type that can be summed. Generally, you should always express algorithms that apply to many argument types with templates. Not only will you reduce code duplication, but you’ll also significantly decrease maintenance times.

Templates are also commonly used when writing containers, as seen in the following example:

template <class T>
class Container
{
public: 
	Container(int length) {
        assert(length > 0);
        data = new T[length]{};
        this.length = length;
    }

	T& operator[](int index) {
	    assert(index >= 0 && index < length);
	    return data[index];
    }
 
    ...
 
	~Container() {
        delete[] data;
    }

private:
	int length{};
	T* data {};
}

A container written this way can be reused for each compatible type, be it primitive or user-defined.

However, there is an additional way to generalize your code. You should always look to augment your algorithms with function objects (functors) to give them a wider usage range.

class Operation {
public:
	Operation() {};
    virtual int operator() (int x, int y) = 0;
};
                                                                                                                                                                                                   
class Add: public Operation {
public:
	Add() {};
	int operator() (int x, int y) override { return x + y; }
};
                                                                                                                                                                                            
class Subtract: public Operation {
public:
	Subtract() {};
	int operator() ( int x, int y) override { return x - y; }
};

int calculate(int x, int y, Operation* operation) {
	return (*operation)(x, y);
}

In this example, the calculate function can be used with any object of type Operation, which gives us the flexibility to use it in various use cases. What’s more, if there is a need to add a new operation, you can do so without changing the function using it.

Although we’ve only scratched the surface of generics, you can see how this powerful mechanism can make your code more DRY and easier to change. It definitely takes some time to get used to, but you’ll go a step further on your quest to write cleaner code.

Stay tuned and happy coding.

AdviceC++Clean CodeConventionsGenericsSoftwareSoftware DevelopmentTemplates
15 Posts
Marko Jovic
  • Java Native Interface with Qt
    Previous PostJava Native Interface with Qt
  • Next PostQt Environment for Android
    Java Native Interface with Qt

Leave a Reply (Cancel reply)

Your email address will not be published. Required fields are marked *

*
*

© 2025 Connection Quest j.d.o.o. All rights reserved.

Copy