Xirdus
Xirdus

Reputation: 3087

operator as template parameter

Is it possible?

template<operator Op> int Calc(int a, b)
{ return a Op b; }

int main()
{ cout << Calc<+>(5,3); }

If not, is way to achieve this without ifs and switches?

Upvotes: 22

Views: 7607

Answers (5)

AshFTW
AshFTW

Reputation: 141

Use

template<typename Op>
int Calc(int a, int b, Op f) {
    return f(a, b);
}

int
main() {
    cout << Calc(5, 3, std::plus{});
    cout << Calc(5, 3, std::minus{});
}

if Dario answer fails with error: cannot deduce template arguments for ‘plus’ from ()

Upvotes: 0

IceFire
IceFire

Reputation: 4137

If you refer to global operators, you have already received some answers. In some particular cases, though, it might also be helpful to use overloaded operator functions.

This might be trivial; nevertheless it might be helpful in some cases which is why I post one example:

#include <iostream>

template<typename opType, typename T>
int operation(opType op, T a, T b)
{
    return (a.*op)(1) + (b.*op)(1);
}

struct linear
{
    int operator()(int n) const {return n;}
    int operator[](int n) const {return n * 10;}
};

int main()
{
    linear a, b;

    std::cout << operation(&linear::operator(), a, b) << std::endl
        << operation(&linear::operator[], a, b);

    return 0;
}

output:

2
20

Upvotes: 0

Dario
Dario

Reputation: 49218

No - templates are about types or primitive values.

You can nontheless pass so called function objects that can be called like functions and carry the desired operator functionality (despite having a nice syntax).

The standard library defines several ones, e.g. std::plus for addition ...

#include <functional>

template<typename Op>
int Calc(int a, int b, Op f) { 
  return f(a, b);
}

int main() { 
  cout << Calc(5,3, std::plus());
  cout << Calc(5,3, std::minus());
}

Upvotes: 20

John Dibling
John Dibling

Reputation: 101456

You can do this using polymorphism:

#include <cstdlib>
#include <iostream>
using namespace std;


class Operator
{
public:
    virtual int operator()(int a, int b) const = 0;
};

class Add : public Operator
{
public:
    int operator()(int a, int b) const
    {
        return a+b;
    }
};

class Sub : public Operator
{
public:
    int operator()(int a, int b) const
    {
        return a-b;
    }
};

class Mul : public Operator
{
public:
    int operator()(int a, int b) const
    {
        return a*b;
    }
};


int main()
{
    Add adder;
    cout << adder(1,2) << endl;
    Sub suber;
    cout << suber(1,2) << endl;
    Mul muler;
    cout << muler(1,2) << endl;
    return 0;
}

Upvotes: 2

Nikola Smiljanić
Nikola Smiljanić

Reputation: 26873

You could use functors for this:

template<typename Op> int Calc(int a, int b)
{
    Op o;
    return o(a, b);
}

Calc<std::plus<int>>(5, 3);

Upvotes: 22

Related Questions