sebrockm
sebrockm

Reputation: 6012

How to define several functions at once that differ only by name (without using macros)?

I have a simple math vector class that basically just wraps a double array.

Now I want to be able to element-wise apply standard math functions on this vector. E.g. my sqrt() implementation looks like this:

MyVector sqrt(MyVector x) // side note: makes a copy of the input vector
{
    for (double& d : x)
        d = std::sqrt(d);
    return x;
}

This works fine. The issue I'm facing is, that I want my vector to be usable with basically all functions in <cmath> that have this signature: double (*)(double).

Note that the implementation of these functions would be identical to the one of sqrt(). The only difference is the function name.

My current solution is a macro:

#define DEFINE(function) \
MyVector function(MyVector x) \
{ \
    for (double& d : x) \
        d = std::function(d); \
    return x; \
}

DEFINE(sqrt)
DEFINE(exp)
DEFINE(sin)
DEFINE(cos)
.
.
.

Is there any non-macro way?

Update

I want these to be free functions to allow generic template code without having to care if the type is a vector or built in.

Upvotes: 1

Views: 79

Answers (1)

Caleth
Caleth

Reputation: 63152

You will have to use a macro to introduce a name, but you can cut down on how long it is

constexpr auto make_op(double(*op)(double))
{
    return [op](MyVector x) 
    { 
        std::transform(std::begin(x), std::end(x), std::begin(x), op); 
        return x; 
    };
}

#define DEFINE(op) constexpr auto op = make_op(std::op);

DEFINE(sqrt)
DEFINE(exp)
DEFINE(sin)
DEFINE(cos)

Note that you may run into issues of redefining those symbols in ::, so it's best to wrap this in a namespace.

See it live!

Upvotes: 3

Related Questions