Reputation: 959
I'm trying to implement Natural numbers with C++, here's the code I have so far (O() is the 0 (zero) number and S(Nat) is the successor function).
// Peano arithmetic C++
// Null element
struct O{
explicit operator const unsigned int() const { return 0; }
};
// Successor function
struct S {
unsigned int val;
explicit operator const unsigned int() const {
// Boundary check
std::cout << "Incremented once" << std::endl;
if (this->val < UINT_MAX) {
return this->val + 1;
}
// Don't wrap around, hit the ceiling and stay there
return this->val;
}
S(const unsigned int a) {
this->val = a;
}
// Constructor
S(const O& zero) {
this->val = 0;
}
S(const S& s) {
this->val = static_cast<const unsigned int>(s);
}
};
// Nat
using Nat = std::variant<O, S>;
int main() {
std::cout << static_cast<const unsigned int>(S(O())) << std::endl;
std::cout << static_cast<const unsigned int>(S(S(O()))) << std::endl;
return 0;
}
What I expected was the static_cast to unsigned to give me 1, 2. What I get is actually 1, 1!
Upvotes: 1
Views: 148
Reputation: 110145
S(const S& s)
is a copy constructor, and the compiler is allowed to elide calls to the copy constructor in certain cases. This is an optional optimization in C++14 and below, and required in C++17. You can verify that this happens here by putting a print statement inside this constructor, which won't print anything.
In this case, it will make the expression S(S(O()))
equivalent to S(O())
.
Therefore, this way of doing things won't work here. You can make S
a function instead, which can return either an integer (making it trivial), or some object if you prefer to keep things similar to your code here.
Upvotes: 2