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!
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.
Related
Without relying on const_cast, how can one make a C++ data member const after but not during construction when there is an expensive-to-compute intermediate value that is needed to calculate multiple data members?
The following minimal, complete, verifiable example further explains the question and its reason. To avoid wasting your time, I recommend that you begin by reading the example's two comments.
#include <iostream>
namespace {
constexpr int initializer {3};
constexpr int ka {10};
constexpr int kb {25};
class T {
private:
int value;
const int a_;
const int b_;
public:
T(int n);
inline int operator()() const { return value; }
inline int a() const { return a_; }
inline int b() const { return b_; }
int &operator--();
};
T::T(const int n): value {n - 1}, a_ {0}, b_ {0}
{
// The integer expensive
// + is to be computed only once and,
// + after the T object has been constructed,
// is not to be stored.
// These requirements must be met without reliance
// on the compiler's optimizer.
const int expensive {n*n*n - 1};
const_cast<int &>(a_) = ka*expensive;
const_cast<int &>(b_) = kb*expensive;
}
int &T::operator--()
{
--value;
// To alter a_ or b_ is forbidden. Therefore, the compiler
// must abort compilation if the next line is uncommented.
//--a_; --b_;
return value;
}
}
int main()
{
T t(initializer);
std::cout << "before decrement, t() == " << t() << "\n";
--t;
std::cout << "after decrement, t() == " << t() << "\n";
std::cout << "t.a() == " << t.a() << "\n";
std::cout << "t.b() == " << t.b() << "\n";
return 0;
}
Output:
before decrement, t() == 2
after decrement, t() == 1
t.a() == 260
t.b() == 650
(I am aware of this previous, beginner's question, but it treats an elementary case. Please see my comments in the code above. My trouble is that I have an expensive initialization I do not wish to perform twice, whose intermediate result I do not wish to store; whereas I still wish the compiler to protect my constant data members once construction is complete. I realize that some C++ programmers avoid constant data members on principle but this is a matter of style. I am not asking how to avoid constant data members; I am asking how to implement them in such a case as mine without resort to const_cast and without wasting memory, execution time, or runtime battery charge.)
FOLLOW-UP
After reading the several answers and experimenting on my PC, I believe that I have taken the wrong approach and, therefore, asked the wrong question. Though C++ does afford const data members, their use tends to run contrary to normal data paradigms. What is a const data member of a variable object, after all? It isn't really constant in the usual sense, is it, for one can overwrite it by using the = operator on its parent object. It is awkward. It does not suit its intended purpose.
#Homer512's comment illustrates the trouble with my approach:
Don't overstress yourself into making members const when it is inconvenient. If anything, it can lead to inefficient code generation, e.g. by making move-construction fall back to copy constructions.
The right way to prevent inadvertent modification to data members that should not change is apparently, simply to provide no interface to change them—and if it is necessary to protect the data members from the class's own member functions, why, #Some programmer dude's answer shows how to do this.
I now doubt that it is possible to handle const data members smoothly in C++. The const is protecting the wrong thing in this case.
Something along these lines perhaps:
class T {
private:
T(int n, int expensive)
: value{n-1}, a_{ka*expensive}, b_{kb*expensive} {}
public:
T(int n) : T(n, n*n*n - 1) {}
};
One possible way could be to put a and b in a second structure, which does the expensive calculation, and then have a constant member of this structure.
Perhaps something like this:
class T {
struct constants {
int a;
int b;
constants(int n) {
const int expensive = ... something involving n...;
a = ka * expensive;
b = kb * expensive;
}
};
constants const c_;
public:
T(int n)
: c_{ n }
{
}
};
With that said, why make a_ and b_ constant in the first place, if you control the class T and its implementation?
If you want to inhibit possible modifications from other developers that might work on the T class, then add plenty of documentation and comments about the values not being allowed to be modified. Then if someone modifies the values of a_ or b_ anyway, then it's their fault for making possibly breaking changes. Good code-review practices and proper version control handling should then be used to point out and possibly blame wrongdoers.
Before describing the answer, I'd first suggest you to re-think your interface. If there's an expensive operation, why don't you let the caller be aware of it and allow them to cache the result? Usually the design forms around the calculations and abstractions that are worth keeping as a state; if it's expensive and reusable, it's definitely worth keeping.
Therefore, I'd suggest to put this to the public interface:
struct ExpensiveResult
{
int expensive;
ExpensiveResult(int n)
: expensive(n*n*n - 1)
{}
};
class T
{
private:
const int a;
const int b;
T(const ExpensiveResult& e)
: a(ka * e.expensive)
, b(kb * e.expensive)
{}
};
Note that ExpensiveResult can be directly constructed from int n (ctor is not explicit), therefore call syntax is similar when you don't cache it; but, caller might, at any time, start storing the result of the expensive calculation.
It's pretty easy to modify the const ints in your object as a result of a significant change in c++20. The library function construct_at and destroy_at have been provided to simplify this. For your class, destroy_at is superfluous since the class contains no members that use dynamic memory like vector, etc. I've made a small modification, added a constructor taking just an int. Also defined an operator= which allows the objects to be manipulated in containers. You can also use construct_at to decrement a_ and b_ in your operator-- method. Here's the code:
#include <iostream>
#include <memory>
namespace {
constexpr int initializer{ 3 };
constexpr int ka{ 10 };
constexpr int kb{ 25 };
class T {
private:
int value;
const int a_{};
const int b_{};
public:
T(int n);
T(int n, int a, int b);
T(const T&) = default;
inline int operator()() const { return value; }
inline int a() const { return a_; }
inline int b() const { return b_; }
int& operator--();
T& operator=(const T& arg) { std::construct_at(this, arg); return *this; };
};
T::T(const int n, const int a, const int b) : value{ n - 1 }, a_{ a }, b_{ b } {}
T::T(const int n) : value{ n - 1 }
{
// The integer expensive
// + is to be computed only once and,
// + after the T object has been constructed,
// is not to be stored.
// These requirements must be met without reliance
// on the compiler's optimizer.
const int expensive{ n * n * n - 1 };
std::construct_at(this, n, ka*expensive, kb*expensive);
}
int& T::operator--()
{
// implement decrements
//--a_; --b_;
const int a_1 = a_ - 1;
const int b_1 = b_ - 1;
std::construct_at(this, value, a_1, b_1);
return value;
}
}
int main()
{
T t(initializer);
std::cout << "before decrement, t() == " << t() << "\n";
--t;
std::cout << "after decrement, t() == " << t() << "\n";
std::cout << "t.a() == " << t.a() << "\n";
std::cout << "t.b() == " << t.b() << "\n";
return 0;
}
Output:
before decrement, t() == 2
after decrement, t() == 1
t.a() == 259
t.b() == 649
I'm trying to figure out how to write "fully generic function" for sqr operation (it's actually can be multiply, division, add, does not really matter).
Consider the following code
#include <iostream>
struct A
{
int val = 2;
A() = default;
A(const A&) = delete; // To make sure we do not copy anything
A(A&& a) = delete; // To make sure we do not move anything
auto operator=(auto) = delete; // To make sure we do not assign anything
// This is important part, we do not want to create a new object on each multiplication.
// We want just to update the old one.
A& operator*(const A& a)
{
val *= a.val;
return *this;
}
};
// Just for easy printing (you can ignore it).
std::ostream &operator<<(std::ostream &os, const A& a) {
return os << a.val;
}
// Here auto&& represents forwarding reference and should automatically understand whether input r or l value.
auto&& sqr(auto&& val)
{
return val * val;
}
int main()
{
A a;
std::cout << sqr(a) << "\n"; // OK
std::cout << sqr(A()) << "\n"; // OK
std::cout << sqr(1) << "\n"; // Wrong, ref to local returned
int i = 2;
std::cout << sqr(i) << "\n"; // Wrong, ref to local returned
}
sqr function here is meant to be sort of generic stuff, it should handle all possible situations (r-values, l-values) and for object a it's actually does, but not for i. I can't get why it's trying to return reference instead of copy. Could anyone please shed some light on the situation? Is there any way I can accomplish this task easily (with one template function ideally)? I can use c++ 20 standard if necessary.
auto&& sqr(auto&& val)
{
return val * val;
}
sqr above always returns a reference. But returning a reference to a local is always wrong. Let the return-type deduce to a non-reference by using auto instead.
constexpr // May be constexpr for some types
auto sqr(auto&& x) // return type is non-reference or trailing
noexcept(noexcept(x*x)) // propagate noexcept
-> decltype(x*x) // enable SFINAE
{ return x * x; }
I am implementing a device_vector in Cuda and i am taking ideas from the well known library Thust.
Now for accessing and modifying an element in that device_vector (v), I need to do v[N] = x. For that i need to overload the [] operator.
This is the code used to overload the [] operator :
T& operator[] (unsigned int index)
{
if (index >= numEle)
return ptr[0];
else
return ptr[index];
}
The problem is : To modify any memory location in Device Memory, we need to make a Cuda Kernel Call and a Cuda kernel call cannot return anything.
As far the [] overloading is concerned it returns the reference to the element we want to modify.
How can we do this for a Cuda Kernel ?
Note : I know Thrust Library somehow does this but I am not able to understand how.
The comments have very good pointers, but as an example, you can create an object that will allow you to use the [] operator to write to the CUDA array directly (or do any other things you choose):
struct CudaVector {
unsigned int get(unsigned int index) {
cout << "Get from device: " << index << endl;
return 0; // TODO read actual value
}
void set(unsigned int index, unsigned int value) {
cout << "Set in device: " << index << " " << value << endl;
// TODO write actual value
}
struct Item {
CudaVector& vector;
unsigned int index;
operator unsigned int() const {
return vector.get(index);
}
unsigned int operator=(unsigned int other) {
vector.set(index, other);
return other;
}
unsigned int operator=(const Item& other) {
return (*this = static_cast<unsigned int>(other));
}
};
Item operator[](unsigned int index) {
return Item{*this, index};
}
};
This works like:
CudaVector vector;
unsigned int foo = vector[8];
vector[5] = vector[6] = vector[7];
Output:
Get from device: 8
Get from device: 7
Set in device: 6 0
Set in device: 5 0
Idea is that your operator[] doesn't return a reference, but instead it returns a temporary object that is able to handle 'reads' (using the conversion operator) and 'writes' (using the assignment operator).
(The second overload is there to allow chained assignments, since the first one won't be picked up automatically if you don't assign from unsigned int first.)
In the C++11, there are two versions of std::unordered_map::operator[], namely:
mapped_type& operator[] ( const key_type& k ); //1
mapped_type& operator[] ( key_type&& k ); //2
There are two questions:
1) Why the second one is necessary - the first one allows to pass constant to the function, since the first one contains the keyword const
2) For example, which version, 1 or 2, will be called in this case:
std::unordered_map<std::string, int> testmap;
testmap["test"] = 1;
Normally, the key is only used for comparison purposes, so you might wonder why rvalue semantics are necessary: a const reference should already cover that case.
But one thing to note is that operator[] can indeed create a new key/value pair: if the key wasn't already existent in the map.
In that case, if the second overload was used, then the map can safely move the provided key value in the map (while default initializing the value). It's a pretty rare and negligible optimization in my opinion, but when you're the C++ standard library, you shouldn't spare any efforts to save someone a cycle, even if it happens just once!
As for the second question, I might be wrong but it should consider the second overload as the best overload.
Edit:
There is also a valid point that it might allow you to use move-only objects as key values, even if it's a debatable decision
It's there for performance reasons. For example if the key is an rvalue, the key is moved instead of copied when a new element is inserted.
Thus, you avoid extra copy of an object/key. You can see this in the following example:
#include <iostream>
#include <unordered_map>
struct Foo {
Foo() { std::cout << "Foo() called" << std::endl; }
Foo(Foo const &other) { std::cout << "Foo(Foo const &other) called" << std::endl; }
Foo(Foo &&other) { std::cout << "Foo(Foo &&other) called" << std::endl; }
int i = 0;
};
bool operator==(Foo const &lhs, Foo const &rhs) {
return lhs.i == rhs.i;
}
void hash_combine(std::size_t& seed, const Foo& v) {
std::hash<int> hasher;
seed ^= hasher(v.i) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
struct CustomHash {
std::size_t operator()(Foo const& v) const {
std::size_t res = 0;
hash_combine(res, v);
return res;
}
};
int main() {
std::unordered_map<Foo, int, CustomHash> fmap;
Foo a;
a.i = 100;
fmap[a] = 100;
fmap[Foo()] = 1;
}
LIVE DEMO
Output:
Foo() called
Foo(Foo const &other) called
Foo() called
Foo(Foo &&other) called
As can see in the case fmap[Foo()] = 1; the rvalue object is moved in contrast with statement fmap[a] = 100; where a copy constructor is called.
I stumbled upon something similar today, and subsequently tried a few things out and noticed that the following seems to be legal in G++:
struct A {
int val_;
A() { }
A(int val) : val_(val) { }
const A& operator=(int val) { val_ = val; return *this; }
int get() { return val_; }
};
struct B : public A {
A getA() { return (((A)*this) = 20); } // legal?
};
int main() {
A a = 10;
B b;
A c = b.getA();
}
So B::getB returns a type A, after it as assigned the value 20 to itself (via the overloaded A::operator=).
After a few tests, it seems that it returns the correct value (c.get would return 20 as one may expect).
So I'm wondering, is this undefined behavior? If this is the case, what exactly makes it so? If not, what would be the advantages of such code?
After careful examination, with the help of #Kerrek SB and #Aaron McDaid, the following:
return (((A)*this) = 20);
...is like shorthand (yet obscure) syntax for:
A a(*this);
return a.operator=(20);
...or even better:
return A(*this) = 20;
...and is therefore defined behavior.
There are a number of quite separate things going on here. The code is valid, however you have made an incorrect assumption in your question. You said
"B::getA returns [...] , after it as assigned the value 20 to itself"
(my emphasis) This is not correct. getA does not modify the object. To verify this, you can simply place const in the method signature. I'll then fully explain.
A getA() const {
cout << this << " in getA() now" << endl;
return (((A)*this) = 20);
}
So what is going on here? Looking at my sample code (I've copied my transcript to the end of this answer):
A a = 10;
This declares an A with the constructor. Pretty straightfoward. This next line:
B b; b.val_ = 15;
B doesn't have any constructors, so I have to write directly to its val_ member (inherited from A).
Before we consider the next line, A c = b.getA();, we must very carefully consider the simpler expression:
b.getA();
This does not modify b, although it might superfically look like it does.
At the end, my sample code prints out the b.val_ and you see that it equals 15 still. It has not changed to 20. c.val_ has changed to 20 of course.
Look inside getA and you see (((A)*this) = 20). Let's break this down:
this // a pointer to the the variable 'b' in main(). It's of type B*
*this // a reference to 'b'. Of type B&
(A)*this // this copies into a new object of type A.
It's worth pausing here. If this was (A&)*this, or even *((A*)this), then it would be a simpler line. But it's (A)*this and therefore this creates a new object of type A and copies the relevant slice from b into it.
(Extra: You might ask how it can copy the slice in. We have a B& reference and we wish to create a new A. By default, the compiler creates a copy constructor A :: A (const A&). The compiler can use this because a reference B& can be naturally cast to a const A&.)
In particular this != &((A)*this). This might be a surprise to you. (Extra: On the other hand this == &((A&)*this) usually (depending on whether there are virtual methods))
Now that we have this new object, we can look at
((A)*this) = 20
This puts the number into this new value. This statement does not affect this->val_.
It would be an error to change getA such that it returned A&. First off, the return value of operator= is const A&, and therefore you can't return it as a A&. But even if you had const A& as the return type, this would be a reference to a temporary local variable created inside getA. It is undefined to return such things.
Finally, we can see that c will take this copy that is returned by value from getA
A c = b.getA();
That is why the current code, where getA returns the copy by value, is safe and well-defined.
== The full program ==
#include <iostream>
using namespace std;
struct A {
int val_;
A() { }
A(int val) : val_(val) { }
const A& operator=(int val) {
cout << this << " in operator= now" << endl; // prove the operator= happens on a different object (the copy)
val_ = val;
return *this;
}
int get() { return val_; }
};
struct B : public A {
A getA() const {
cout << this << " in getA() now" << endl; // the address of b
return (((A)*this) = 20);
// The preceding line does four things:
// 1. Take the current object, *this
// 2. Copy a slice of it into a new temporary object of type A
// 3. Assign 20 to this temporary copy
// 4. Return this by value
} // legal? Yes
};
int main() {
A a = 10;
B b; b.val_ = 15;
A c = b.getA();
cout << b.get() << endl; // expect 15
cout << c.get() << endl; // expect 20
B* b2 = &b;
A a2 = *b2;
cout << b2->get() << endl; // expect 15
cout << a2.get() << endl; // expect 15
}