DEV Community

Mark Nefedov
Mark Nefedov

Posted on • Edited on

Template based configuration.

Templates can be used, to avoid virtual function calls.

#include <iostream>

struct Impl1{
    void Run(){
        std::cout << "Impl1" << std::endl;
    }
};

struct Impl2{
    void Run(){
        std::cout << "Impl2" << std::endl;
    }
};


template<typename T>
struct Runner{
    T RunImplementation;
    void MainLoop(){        
        RunImplementation.Run();
    }
};

int main()
{
  Runner<Impl1> loop1;
  Runner<Impl2> loop2;
  loop1.MainLoop();
  loop2.MainLoop();
}
Enter fullscreen mode Exit fullscreen mode

Types can be selected at compile-time, this can be useful if you want to implement some kind of adaptive templates. For example you can store big objects on the heap and small in the stack.

template<typename T>
using sharedPtrTypeSelector = 
    typename std::conditional<sizeof(T) <= sizeof(std::shared_ptr<T>), T, std::shared_ptr<T>>::type;

    template<typename T>
    class swStorage{
        sharedPtrTypeSelector<T> data;
    public:
        bool operator==(const swStorage &rhs) const {
            if constexpr (std::is_pointer_v<sharedPtrTypeSelector<T>>)
                return *data == *rhs.data;
            else
                return data == rhs.data;
        }
        bool operator!=(const swStorage &rhs) const {
            return !(rhs == *this);
        }

        operator T() const {
            if constexpr (std::is_pointer_v<sharedPtrTypeSelector<T>>)
                return *data;
            else
                return data;
        }

        swStorage(){
            if constexpr (std::is_pointer_v<sharedPtrTypeSelector<T>>)
                data = std::make_shared<T>(0);
        }

        explicit swStorage(const T& newData){
            if constexpr (std::is_pointer_v<sharedPtrTypeSelector<T>>)
                data = std::make_shared<T>(newData);
            else
                data = newData;
        }
    };
Enter fullscreen mode Exit fullscreen mode

For example, I've used it to optimize storage in an Octree.

GitHub logo marknefedov / cubic-octree

Cubic octree, with on-demand node allocation.

Cubic-octree CodeFactor Codacy Badge

Cubic octree with array-like access. Originally made to store voxel data for minecraft-like terrain.

Example

Octree<int, 5> octree; // This will create octree of size 32x32x32 with only root node allocated
octree.set(1, 2, 3, 4) // This will allocate nodes down to depth of 5 and set node at position [1,2,3] to value 4.
int val = octree.get(1, 2, 3) // Get value at node [1,2,3]
octree.SimplifyTree() // Collapse nodes with same values.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)