-4

In numerical programming I frequently want to raise a number to a power inside an expression. This leads to code that has hundreds of occurrences of pow(x,2) or something of the sort.

This clutters the code and makes it less readable and less easy to parse, especially when comparing written equations with code.

I want to write an operator for exponentiation in C++, if this is at all possible.

a^b == pow(a, b)

I've tried writing an overload for operator()(double, double) or operator[](double, double) (chosen because it binds tighter than (binary) *. However I can't make it work.

Is something like this in any way possible?

Maybe preprocessor trickery?

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
andrepd
  • 587
  • 6
  • 20
  • 3
    I recommend removing all your value judgements about the relative importance of doing this, as it will just get you attention that isn't actually helpful, and it doesn't contribute to understanding your question. – xaxxon Jun 24 '17 at 00:51
  • 6
    One shall not overload operators for builtin types, but you can write wrapper classes and overload `operator^` or whatever you want. In my opinion, this is unnecessary and will cause confusion, as people are used to `operator^` being XOR. – DeiDei Jun 24 '17 at 00:53
  • This just cannot be done, since you cannot overload operators that only involve primitive types, and there's no token that can be redefined by the preprocessor (you cannot have a macro named as numbers or as `^`). – Matteo Italia Jun 24 '17 at 00:54
  • @xaxxon I think it does. I was trying to explain my motivation for "breaking the rules", so to speak, lest someone come to give advice amounting to "you shouldn't do it like so". – andrepd Jun 24 '17 at 00:54
  • @DeiDei, Thank you for the suggestion. That would however involve redefining all operators etc. to behave as if they were a double. So lot's of `MyDouble operator+(MyDouble x, MyDouble y){return MyDouble(x.data+y.data);}`, where `x.data` is a `double`, if I make myself clear (this because one can't inherit from primitive types. – andrepd Jun 24 '17 at 01:00
  • @xaxxon That's surely because you don't do numerical work :) – andrepd Jun 24 '17 at 01:01
  • @andrepd but that's not what you said. You said in all of c++ it was frequent, but even more so in numerical programming. This is why I was suggesting you just remove it. – xaxxon Jun 24 '17 at 01:02
  • @andrepd Yeah, in the end `pow(a, b)` is the way to go. All solutions would be too much unjustified effort. – DeiDei Jun 24 '17 at 01:02
  • @andrepd You can take a look at [this](http://ideone.com/WXJIPx). – DeiDei Jun 24 '17 at 01:10
  • 1
    I don't understand all the downvotes. The question is reasonable and useful. Also well answerable as been proven. – πάντα ῥεῖ Jun 24 '17 at 09:54
  • @DeiDei Gotcha. That's very helpful. I forgot you could just declare the implicit `double` cast. That solves a lot of issues. – andrepd Jun 24 '17 at 13:27

2 Answers2

2

Something like this?

#include <iostream>
#include <cmath>

using namespace std;

class Exp {
 public:
  double val ;
  Exp(double val) : val(val) {}
  Exp operator^(const Exp &exp) {
      return Exp(pow(val, exp.val));
  }
  operator double () {
    return val;
  }
};

ostream &operator << (ostream &out, const Exp &exp) {
  out << exp.val;
  return out;
}


int main(){
   Exp a = 2;
   Exp b = 3;

   cout << (a + b) << ", " << (a ^ b) << endl;

   return 0;
 }
Serge
  • 11,616
  • 3
  • 18
  • 28
  • That's fine for doing the power of two `Exp`. But what if I want to, say, add them? Worse, what if I want to add an `Exp` and a `double`? I would have to manually redeclare all operators? – andrepd Jun 24 '17 at 13:26
  • In this particular case you can overload cast to double as well. I added it to the example. – Serge Jun 24 '17 at 13:54
0

You can define your own user-defined literal which returns an object with call operator to perform the exponentiation, as in

5.123_E(3)

The obvious downside of this approach is that it only works with literals values, i.e. no a_E(b) (although 5.123_E(b) would work).

#include <iostream>
#include <cmath>

template < typename T >
class Exponential
{
  T m_base;
public:
  Exponential(T base) : m_base{base} {}
  template < typename R >
  decltype(auto) operator()(R exponent) { return std::pow(m_base,exponent); }
};

Exponential<long double> operator "" _E(long double base) { return Exponential<long double>{base}; }

int main()
{
  std::cout << (5.123_E(3)) << std::endl;
}
Henri Menke
  • 10,705
  • 1
  • 24
  • 42