C++ Extension functions?

One method I have found is to use the overloaded ">>" operator with lambda expressions. The following code demonstrates this. You have to know to use operator ">>" instead of "->", this is because the compiler I use will not allow the operator "->" to be overloaded. Also because the operator ">>" has lower precedence than the "->" you have to use parentheses to force to compiler to evaluate the equation in the correct order.

In the end it becomes a matter of style, maintainability, reliability and cleanness of the code you are trying to produce. One would argue defining the "SubtractValue" method with two arguments creates more efficient code, but others would argue the overloaded method is more maintainable. In the end it is left to the architects and developers to determine what is important to their project. I am just providing a possible solution to the issue.

#include <functional>
#include <iostream>
#include <stdio.h>
#include <tchar.h>

// Some plain demo class that cannot be changed.
class DemoClass
{
public:
    int GetValue() { return _value; }
    int SetValue(int ivalue) { _value = ivalue; return _value; }
    DemoClass *AddValue(int iadd) { this->_value += iadd; return this; }

private:
    int _value = 0;
};

// Define Lambda expression type that takes and returns a reference to the object.
typedef std::function<DemoClass *(DemoClass *obj)> DemoClassExtension;

// Overload the ">>" operator because we cannot overload "->" to execute the extension.
DemoClass* operator>>(DemoClass *pobj, DemoClassExtension &method)
{
    return method(pobj);
}

// Typical extensions.

// Subtract value "isub".
DemoClassExtension SubtractValue(int isub)
{
    return [=](DemoClass *pobj) {
        pobj->AddValue(-isub);
        return pobj;
    };
}

// Multiply value "imult".
DemoClassExtension MultiplyValue(int imult)
{
    return [=](DemoClass *pobj) {
        pobj->SetValue(pobj->GetValue() * imult);
        return pobj;
    };
}

int _tmain(int argc, _TCHAR* argv[])
{
    DemoClass *pDemoObject = new DemoClass();
    int value = (pDemoObject->AddValue(14) >> SubtractValue(4) >> MultiplyValue(2))->GetValue();
    std::cout << "Value is " << value;
    return 0;
}

The above code output is "Value is 20".


There are no extension functions in C++. You can just define them as free functions.

uint SwapEndian(uint value){ ... }

Extension methods (and also "static classes") exist in C#/Java languages solely because the designers decided that (the Java way of) OOP is The One True Way and that everything must be a method from a class:

This is not C++ way of doing things. In C++ you have namespaces, free functions and Koenig lookup to extend the behavior of a class:

namespace foo
{
    struct bar { ... };

    void act_on_bar(const bar& b) { ... };
}

...

foo::bar b;
act_on_bar(b); // No need to qualify because of Koenig lookup

I usually consider extension methods harmful. If you attach too much behavior to a class, you are proabably failing to capture the reason why the class exists. Also (like "partial classes"), they tend to make the code related to a class non local. Which is bad.

As to your problem, in C++ you simply do:

template <typename T>
T swap_endian(T x)
{
    union { T value; char bytes[sizeof(T)]; } u;
    u.value = x;

    for (size_t i = 0; i < sizeof(T)/2; i++) 
        swap(u.bytes[i], u.bytes[sizeof(T) - i - 1]);

    return u.value;
}

Usage:

swap_endian<std::uint32_t>(42);

or, if the type can be deduced:

std::uint64_t x = 42;
std::uint64_t y = swap_endian(x);

Tags:

C++