Skip to main content
Updated to note that `std::pow()` is not guaranteed to be `constexpr`.
Source Link
G. Sliepen
  • 61.7k
  • 3
  • 61
  • 152

You canmight be able to use std::pow() in constexpr expressions in C++11

Since this post was not tagged "reinventing-the-wheel", I want to point out that some compilers (notably GCC) will compile the following code is validbelow C++11 code:

#include <cmath>

constexpr int ipow(int a, int b) {
    return std::pow(a, b);
}

int main(int argc, char *argv[]) {
    static_assert(ipow(-5, 3) == -125);
    return ipow(argc, 2);
}

The onlyOne drawback is that std::pow() converts integer arguments to double, which at run-time may or may not result in slower computation than using int. Also, while for int there is no loss of precision, if you would want to use int64_t, there is a potential loss of precision.

The other drawback, as pointed out by Oliver Schonrock, is that not all compilers allow constexpr use of std::pow(). As explained in this post, constexpr math functions were only allowed in C++11 but not in C++14. But there are libraries that provide constexpr math functions, see for example Sprout's pow() implementation.

Zero to the power zero is one*

With most programming languages, one usually finds that pow(0, 0) == 1. You should ensure your solution also returns one in that case, to ensure consistency, regardless of your personal feelings about zero to the power zero.

As a bonus, by having a well-defined result for ipow(0, 0), it no longer throws exceptions, and you can get rid of some of the specializations.

Catch exceptions by const reference

Make it a habit to catch exceptions by const reference. Apart from being a little bit faster (although this of course is the least of your worries when exceptions are being thrown), it ensures you don't lose information when the exception thrown is of a derived class. See this StackOverflow question for more information.

You can use std::pow() in constexpr expressions

Since this post was not tagged "reinventing-the-wheel", I want to point out that the following code is valid C++11:

#include <cmath>

constexpr int ipow(int a, int b) {
    return std::pow(a, b);
}

int main(int argc, char *argv[]) {
    static_assert(ipow(-5, 3) == -125);
    return ipow(argc, 2);
}

The only drawback is that std::pow() converts integer arguments to double, which at run-time may or may not result in slower computation than using int. Also, while for int there is no loss of precision, if you would want to use int64_t, there is a potential loss of precision.

Zero to the power zero is one*

With most programming languages, one usually finds that pow(0, 0) == 1. You should ensure your solution also returns one in that case, to ensure consistency, regardless of your personal feelings about zero to the power zero.

As a bonus, by having a well-defined result for ipow(0, 0), it no longer throws exceptions, and you can get rid of some of the specializations.

Catch exceptions by const reference

Make it a habit to catch exceptions by const reference. Apart from being a little bit faster (although this of course is the least of your worries when exceptions are being thrown), it ensures you don't lose information when the exception thrown is of a derived class. See this StackOverflow question for more information.

You might be able to use std::pow() in constexpr expressions in C++11

Since this post was not tagged "reinventing-the-wheel", I want to point out that some compilers (notably GCC) will compile the below C++11 code:

#include <cmath>

constexpr int ipow(int a, int b) {
    return std::pow(a, b);
}

int main(int argc, char *argv[]) {
    static_assert(ipow(-5, 3) == -125);
    return ipow(argc, 2);
}

One drawback is that std::pow() converts integer arguments to double, which at run-time may or may not result in slower computation than using int. Also, while for int there is no loss of precision, if you would want to use int64_t, there is a potential loss of precision.

The other drawback, as pointed out by Oliver Schonrock, is that not all compilers allow constexpr use of std::pow(). As explained in this post, constexpr math functions were only allowed in C++11 but not in C++14. But there are libraries that provide constexpr math functions, see for example Sprout's pow() implementation.

Zero to the power zero is one*

With most programming languages, one usually finds that pow(0, 0) == 1. You should ensure your solution also returns one in that case, to ensure consistency, regardless of your personal feelings about zero to the power zero.

As a bonus, by having a well-defined result for ipow(0, 0), it no longer throws exceptions, and you can get rid of some of the specializations.

Catch exceptions by const reference

Make it a habit to catch exceptions by const reference. Apart from being a little bit faster (although this of course is the least of your worries when exceptions are being thrown), it ensures you don't lose information when the exception thrown is of a derived class. See this StackOverflow question for more information.

Source Link
G. Sliepen
  • 61.7k
  • 3
  • 61
  • 152

You can use std::pow() in constexpr expressions

Since this post was not tagged "reinventing-the-wheel", I want to point out that the following code is valid C++11:

#include <cmath>

constexpr int ipow(int a, int b) {
    return std::pow(a, b);
}

int main(int argc, char *argv[]) {
    static_assert(ipow(-5, 3) == -125);
    return ipow(argc, 2);
}

The only drawback is that std::pow() converts integer arguments to double, which at run-time may or may not result in slower computation than using int. Also, while for int there is no loss of precision, if you would want to use int64_t, there is a potential loss of precision.

Zero to the power zero is one*

With most programming languages, one usually finds that pow(0, 0) == 1. You should ensure your solution also returns one in that case, to ensure consistency, regardless of your personal feelings about zero to the power zero.

As a bonus, by having a well-defined result for ipow(0, 0), it no longer throws exceptions, and you can get rid of some of the specializations.

Catch exceptions by const reference

Make it a habit to catch exceptions by const reference. Apart from being a little bit faster (although this of course is the least of your worries when exceptions are being thrown), it ensures you don't lose information when the exception thrown is of a derived class. See this StackOverflow question for more information.