I wrote a function calculating the gcd of two numbers which uses std::swap
in the case where the second parameter is greater than the first.
Some time later, I realised that std::swap
is not constexpr
, but my function still compiled and ran successfully.
I tried with MinGW-w64 8.1.0 and Visual C++ 2017 and it worked for both.
My first thought was that's because constexpr
functions are allowed to be executed at runtime, so I tried std::integral_constant<int,gcd(32,12)>
, and it worked.
However, I cannot use any of my own non-constexpr function (which is what I expect).
Here is my test code :
#include <utility>
inline void foo() noexcept {
}
template<typename T>
constexpr T gcd(T a, T b) {
// foo(); // only works with non-constexpr j
if(a<b) {
std::swap(a, b); // works for both constexpr i and non-constexpr j
}
if(b==0) {
return a;
} else {
return gcd(b, a%b);
}
}
int main()
{
constexpr int i = std::integral_constant<int, gcd(32, 12)>::value;
int j = gcd(32,12);
}
So, my question is : why can I use std::swap
in my function ?
Here is a relevant quote from cppreference:
A constexpr function must satisfy the following requirements:
- ...
- there exists at least one set of argument values such that an invocation of the function could be an evaluated subexpression of a core constant expression
There is a path that does not go through std::swap()
, where a a>=b
. In fact, for gcd(32, 12)
the execution never goes through std::swap()
.
EDIT: I had a look at the C++14 draft. Section 7.1.5 The constexpr specifier. Paragraph 5 says:
For a non-template, non-defaulted constexpr function [...], if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (5.20), or, for a constructor, a constant initializer for some object (3.6.2), the program is ill-formed;
and the example they give is:
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // OK
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With