user9985127
user9985127

Reputation: 185

How to pass numeric operator as a parameter?

In C++, we can do something like the following,

template <class OP>
int f(OP op){
   return op(1,2);
}

int main(){
    int res1 = f(std::plus<int>{});
    int res2 = f(std::multiplies<int>{});
}

How could I do the same thing with simple numeric operator,

int main(){
    int res1 = f(+);
    int res2 = f(*);
}

Exactly, what I want to know is how to write the line of 'return' in function f.

Upvotes: 0

Views: 192

Answers (1)

eerorika
eerorika

Reputation: 238341

How could I do the same thing with simple numeric operator,

You cannot; not using a function template. Operators are not something that can be passed as arguments or stored in objects.

what I want to know is how to write the line of 'return' in function f.

There is no way you can write f as a function template that would make f(+) work because f(+) would be syntactically ill-formed.

As shown in a comment, that can be done using a macro:

#define MY_MACRO_WITH_UNIQUE_NAME(op) \
[]{                                   \
    return 1 op 2;                    \
}()

int res1 = MY_MACRO_WITH_UNIQUE_NAME(+);
int res2 = MY_MACRO_WITH_UNIQUE_NAME(*);

#undef MY_MACRO_WITH_UNIQUE_NAME

Note that macros are prone to name collisions, so make sure that the name you pick isn't used nor is likely to be used by others.

There's no reason to do this rather than just using the template and std::plus that you wrote initially. Macros are useful though for defining a set of identical operator overloads for example, because in that case you cannot avoid using the operator symbol. Here is something that I've written:

#define FOO_DEFINE_OP(op, trait)                                     \
    template <class T, class = std::enable_if_t<trait<T>::value> >   \
    constexpr bool operator op(const foo<T>& lhs, const foo<T>& rhs) \
    {                                                                \
        return lhs.t op rhs.t;                                       \
    }

FOO_DEFINE_OP(==, boost::has_equal_to)
FOO_DEFINE_OP(!=, boost::has_not_equal_to)
FOO_DEFINE_OP(<,  boost::has_less)
FOO_DEFINE_OP(<=, boost::has_less_equal)
FOO_DEFINE_OP(>,  boost::has_greater)
FOO_DEFINE_OP(>=, boost::has_greater_equal)

#undef FOO_DEFINE_OP

This should hopefully become less needed with the introduction of defaulted comparison operators in C++20.

Upvotes: 3

Related Questions