What does range-for loop exactly do? - c++

I'm working on a snake game program. I use a deque of Body in class Snake to represent a snake and of course Body is a struct I have defined. Here is part of the code:
struct Body { // one part of snake body
int x, y, direction;
Body() : x(0), y(0), direction(UP) { }
Body(int ix, int iy, int id) : x(ix), y(iy), direction(id) { }
};
class Snake {
protected:
std::deque<Body> body;
// other members
public:
auto begin()->std::deque<Body>::const_iterator const { return body.cbegin(); }
auto end()->std::deque<Body>::const_iterator const { return body.cend(); }
// other members
};
And in another function construct_random_food I need to generate a food and make sure it does not coincide with the snake. Here's the function definition:
Food construct_random_food(int gameSize, const Snake& snake) {
static std::random_device rd;
static std::uniform_int_distribution<> u(2, gameSize + 1);
static std::default_random_engine e(rd());
Food f;
while (1) {
f.x = u(e) * 2 - 1;
f.y = u(e);
bool coincide = 0;
for (const auto& bd : snake) // This causes an error.
if (bd.x == f.x && bd.y == f.y) {
coincide = 1; break;
}
if (!coincide) break;
}
return f;
}
An error is caused at the range-based for-loops line. It says that I'm trying to cast const Snake to Snake& (casting a low-level const away). I fix the problem by rewriting that line like this:
for (const auto& fd : const_cast<Snake&>(snake))
So I'm wondering what exactly a range-for do and what it needs. Does the error have anything to do with the begin() function in class Snake?

The problem is that your begin and end functions are not const.
auto begin()->std::deque<Body>::const_iterator const { return body.cbegin(); }
// this applies to the return type ^^^^^
You've applied the const qualifier to the return type, not to the calling object. Put the const qualifier before the trailing return type.
auto begin() const ->std::deque<Body>::const_iterator { return body.cbegin(); }
You can see the correct order in which you should place function qualifiers here: http://en.cppreference.com/w/cpp/language/function

Related

Is it possible to initialize a data member as const based on a bool passed in as argument in the constructor?

I have a class that takes in a boolean called fixed as an argument. I want it to initialize the data member position as const if fixed is true. Is this possible at all?
class PhysicsVertex
{
public:
PhysicsVertex(olc::vf2d position, const bool fixed = false) :
position(position), fixed(fixed)
{
}
olc::vf2d position; //make this const if fixed is true.
const bool fixed = false;
};
int main()
{
PhysicsVertex v1{ {0, 0}, true }; //initialize v1.position as const
PhysicsVertex v1{ {0, 0} }; //initialize v1.position as non-const
}
If your information about fixed parameter is needed at compile time then you can use templates
#include <type_traits>
struct vf2d
{
};
template <bool fixed>
class PhysicsVertex
{
public:
PhysicsVertex() :
position()
{
}
typename std::conditional<fixed, const vf2d, vf2d>::type position;
};
void foo()
{
auto vertex = PhysicsVertex<true>();
// vertex.position = vf2d(); - compile time error, you cannot change const member
auto vertex2 = PhysicsVertex<false>();
vertex2.position = vf2d(); // It works fine, you can change non const member
}
const class members are problematic, because they inhibit a whole bunch of compiler generated methods. For example PhysicsVertex cannot be copied. Often the better alternative is to not make it const but instead provide no means to modify it from outside the class:
class foo {
int x = 42;
public:
int get() { return x; }
};
The member is not modifyable.
Now to your quesiton. You cannot make it const or non-const based on a runtime value (at least not easily), but following the suggestion above you can conditionally allow to modify it or not:
class foo {
int x = 42;
bool modifyable = false;
public:
foo(bool modifyable) : modifyable(modifyable) {}
void set(int y) {
if (!modifyable) throw "cannot modify";
x = y;
}
};
You should reconsider whether you can already decide to make it const or non-const at compile time, because then you need not rely on runtime checks and excpetions but can use the approach described in this answer.

C++ using vector as static container for class instances

I use a vector as static member of a class to count all the instance of the class itself and its derived classes. However When trying to resize the container I get a stack-overflow thrown from the vector itself.
// initialize static values:
auto_ptr<HandleManager> ID3OBJ::HM = auto_ptr<HandleManager>(new HandleManager());
auto_ptr<vector<shared_ptr<ID3OBJ>>> ID3OBJ::ObjectList = auto_ptr<vector<shared_ptr<ID3OBJ>>>(new vector<shared_ptr<ID3OBJ>>{});
I initialize the static member as empty as shown above.
// constructors:
ID3OBJ::ID3OBJ(double x, double y, double z) : X(x), Y(y), Z(z), Handle(this->HM->addHandle()) { ObjectList->push_back(auto_ptr<ID3OBJ>(this));}
ID3OBJ::ID3OBJ() : X(0), Y(0), Z(0), Handle(this->HM->addHandle()) { ObjectList->push_back(shared_ptr<ID3OBJ>(this));}
Vector::Vector(double x, double y, double z) { X = x; Y = y; Z = z;
ObjectList->push_back(auto_ptr<Vector>(this));}
Vector::Vector() {
X = 0; Y = 0; Z = 0;
ObjectList->push_back(shared_ptr<Vector>(this));}
The constructors add any new instance to the instancelist, which is called ObjectList. This is working as intended.
// deconstructors:
ID3OBJ::~ID3OBJ()
{
string tempH = this->Handle;
auto iter = ObjectList->end();
if (ObjectList->size() == HM->assignedHandles())
{
iter = remove_if(ObjectList->begin(), ObjectList->end(), [&](shared_ptr<ID3OBJ> ptr) {return ptr->getHandle() == tempH; });
}
ObjectList->erase(iter, ObjectList->end());
this->HM->removeHandle(this->Handle);
}
Vector::~Vector()
{
string tempH = this->Handle;
auto iter = ObjectList->end();
if (ObjectList->size() == HM->assignedHandles())
{
iter=remove_if(ObjectList->begin(), ObjectList->end(), [&](shared_ptr<ID3OBJ> ptr) {return ptr->getHandle() == tempH; });
}
ObjectList->erase(iter, ObjectList->end());
}
As far as I understand remove_if replaces any occurances whose pred returns true with the element after the occurance. Means if the pred with vec[3] as argument returns true, vec[2] points to vec[4] instead of vec[3].
Hence the erase function is needed to shorten the container length, however as soon as I implement this shortening an error occurs.
Header File:
// class-name: ID3OBJ
// Date: 30.01.2017
// Version: 1.0
// Description: The class works as base class for all used 3D-Objects, and defines the operations all 3D-Objects have, namely the Direction in case of a vector, or origion in all other cases
//
class ID3OBJ
{
public:
double X;
double Y;
double Z;
static auto_ptr<vector<shared_ptr<ID3OBJ>>> ObjectList;
ID3OBJ(double x, double y, double z);
ID3OBJ();
~ID3OBJ();
const string getHandle();
protected:
string Handle;
static auto_ptr<HandleManager> HM;
};
// class-name: I3DM
// Date: 23.03.2017
// Version: 1.0
// Description: The class works as Interface for classes which can do Vector-operations
//
template <class T> class I3DM : public virtual ID3OBJ
{
public:
using ID3OBJ::X;
using ID3OBJ::Y;
using ID3OBJ::Z;
static auto_ptr<vector<shared_ptr<T>>> ObjectList;
protected:
using ID3OBJ::Handle;
using ID3OBJ::HM;
};
// class-name: Vector
// Date: 30.01.2017
// Version: 1.0
// Description: The class works as vector, it provides an interface to acces and modify vectors, aswell as most of the vector operations
//
class Vector : public virtual I3DM<Vector>
{
public:
using I3DM<Vector>::X;
using I3DM<Vector>::Y;
using I3DM<Vector>::Z;
using I3DM<Vector>::ObjectList;
Vector(double x, double y, double z);
Vector();
~Vector();
//I'm not sure if the protected members have to be provided aswell in the header file
protected:
using ID3OBJ::Handle;
using ID3OBJ::HM;
};
HM-header:
class HandleManager
{
public:
HandleManager();
const int assignedHandles();
const string addHandle();
void removeHandle(string hexstring);
protected:
int AssignedHandles;
forward_list<int> FreeHandles;
bool FreeHandlesAvailable;
};
CPP:
const int string_to_hex(string s)
{
int returnvalue;
stringstream stream;
stream << hex << s;
stream >> returnvalue;
return returnvalue;
}
HandleManager::HandleManager()
{
this->FreeHandlesAvailable = false;
this->AssignedHandles = 0;
}
const int HandleManager::assignedHandles()
{
return this->AssignedHandles;
}
const string HandleManager::addHandle()
{
string returnValue;
if (this->FreeHandlesAvailable)
{
returnValue = int_to_hex(this->FreeHandles.front());
this->FreeHandles.pop_front();
this->AssignedHandles++;
if (this->FreeHandles.empty()) { this->FreeHandlesAvailable = false; }
}
else
{
returnValue = int_to_hex(this->AssignedHandles);
this->AssignedHandles++;
if (this->AssignedHandles == 1) { returnValue = int_to_hex((int)0); }
}
return returnValue;
}
void HandleManager::removeHandle(string hexstring)
{
this->FreeHandlesAvailable = true;
this->FreeHandles.push_front(string_to_hex(hexstring));
this->AssignedHandles--;
}
error message:
Unhandled exception at 0x00C01899 in RVE.exe: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x01002F48). occurred
The parameter 0x00000001 is most likely a handle, is there any way to search for the object which has the memory adress given? (0x01002F48)
Consider what happens when you remove an ID3OBJ from the vector:
The vector will destroy the auto_ptr<ID3OBJ>...
Which will try to destroy the ID3OBJ...
Whose destructor will try to remove the auto_ptr<ID3OBJ> from the vector...
Which will destroy the auto_ptr<ID3OBJ>... and we go back to step 1.
This process will recurse until the stack is overflowed. The same is true for the Vector vector too. (Roger, Roger. What's your vector, Victor?)
The standard library vector is not designed to be re-entrant; if a member of vector winds up calling itself, the behavior is undefined. In your case, vector::erase() indirectly calls itself through your destructors.
Therefore, your program's behavior is undefined.
auto_ptr<..>(this), shared_ptr<..>(this) or unique_ptr<..>(this) is never correct and a bug waiting to happen. Smart pointers take values from allocated memory, this is pointer to an object and you do not know how it came about. You are effectively doing something like the following,
int a;
auto_ptr< int > ap0( &a ); // certain death.
shared_ptr< int > ap1( &a ); // also certain death.
or equally bad,
auto_ptr< int > ap( new int );
auto_ptr< int > ap0( ap.get() ); // certain death.
shared_ptr< int > ap1( ap.get() ); // also certain death.
It is hard to understand what you are trying to achieve. If you simply want to track instances your vector should definitely be raw pointers. If your purpose is memory management, then I can't see how this could work from your code.

how to forbid assignment to not reference variables?

I fear it's a dumb question but...
Someone can suggest me a way to force that a return value from a function (or a method), that return a reference to an internal static variable or a member of the class/struct, is assigned only to reference variables ?
I try to explain what I desire with a minimal example.
Given the following code, with a function wrapValue() that return a reference to the internal static variable,
int & wrapValue (int v0)
{
static int val;
return val = v0;
}
int main ()
{
// how to permit this ...
int & v0 { wrapValue(0) };
// ... but forbid this ...
int v1 { wrapValue(1) };
int v2;
// ... and this ?
v2 = wrapValue(2);
}
there is a way to permit the initialization of v0 (and bound v0 to the static variable) and forbid the initialization of v1 and the assignment of v2 (without bounding v1 and v2 to the static variable) ?
And if it's impossible with the current C++ standard, as I fear, someone can suggest me an alternative way (but not too complex: I intend use it in a library that I want to maintain simple) to forbid an unbounded assignment ?
This solution is somewhat tricky but it works (I think) as you expect:
#include <iostream>
struct int_wrapper {
int value;
int_wrapper &operator=(int value) {
this->value = value;
return *this;
}
operator int&() {
return value;
}
operator int() {
return value;
}
};
int_wrapper& wrapValue (int v0) {
static int_wrapper val;
return val = v0;
}
int main () {
// how to permit this ...
int & v0 = wrapValue(0);
// ... but forbid this ...
//int v1 { wrapValue(1) }; // call ambigious
int v2;
(void)v0;
(void)v2;
// ... and this ?
//v2 = wrapValue(2); // call ambigious
}
[live demo]
As far as I know int is copyable, so people can copy if they like; you cannot prevent this. However, you could create a wrapper class that is non-copyable.
class NonCopyableInt
{
int val;
public:
NonCopyableInt(int val) : val(val) {}
NonCopyableInt(NonCopyableInt&) = delete;
int& value() { return val; }
// todo: add some nice operators and functions such as assignment from int
}
NonCopyableInt& wrapValue (int v0)
{
static NonCopyableInt val;
return val = v0;
}
However, people could always copy the return value from value() so you end up with the same problem. And it feels really clunky and meh.

std::bind requires default constructor

Im working on a project to school(as namespace name may hint, it is 2D game) and Ive made a custom class called RangeInt(Range) which just wraps two variables of same type and made another class called Randomizer which wraps the C++11 standard random number generation and uses the RangeInt class to specify the range I want to generate the numbers.
Well anyways here is the code:
namespace game{
template<class _Type>
//very simple class representing virtual Range
//of type _Type(template argument) and storing
//upper and lower bound
class Range{
public:
typedef _Type TemplateParam;
//value sto use of type _Type
_Type first, second;
//copy constructor:
Range(const Range& rng)
{
first = rng.first;
second = rng.second;
}
//move construct:
Range(Range&& rng)
{
std::swap(*this, rng);
}
Range& operator=(const Range& range)
{
first = range.first;
second = range.second;
return *this;
}
Range& operator=(Range&& range)
{
std::swap(first, range.first);
std::swap(second, range.second);
return *this;
}
//constructor
Range(_Type one, _Type two) : first(one), second(two) {}
//returns two - one
inline _Type getDifference() { return two - one; }
};
typedef Range<uint> RangeInt;
};
and the randomizer:
namespace game{
template <class _RNG = xorshift>
class Randomizer_RNG{
typedef _RNG random_generator;
RangeInt rng;
random_generator mt;
std::uniform_int_distribution<> dist;
//reinitialize the dist variable so it actually knows the new range
void _changeDist()
{
dist = std::uniform_int_distribution<>(rng.first, rng.second);
}
public:
//default constructor, set rng to maximum range and initialize
//the xorshift with seed being current time and specify the
//range for uniform_int_distribution
Randomizer_RNG()
{
rng = game::RangeInt(0, std::numeric_limits<game::uint>::max());
dist = std::uniform_int_distribution<>(range.first, range.second);
mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
}
//do the same as constructor above but with specified range
explicit Randomizer_RNG(RangeInt range) : rng(range)
{
dist = std::uniform_int_distribution<>(rng.first, rng.second);
mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
}
//copy constructor
Randomizer_RNG(const Randomizer_RNG& lhs)
{
dist = lhs.dist;
mt = lhs.mt;
rng = lhs.rng;
}
//move constructor
Randomizer_RNG(Randomizer_RNG&& lhs)
{
std::swap(*this, lhs);
}
//reseed with current time
inline void seed()
{
mt.seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
}
//reseed with specified value
inline void seed(unsigned long long newSeed)
{
mt.seed(newSeed);
}
//default operator()
uint32 operator()()
{
return dist(mt);
}
//return value generated in range of
//<fitWithin.first, fitWithin.second>
uint32 operator()(RangeInt&& fitWithin)
{
decltype(dist) l_dist(fitWithin.first, fitWithin.second);
return l_dist(mt);
}
//the same as above, but with rvalue reference
uint32 operator()(RangeInt& fitWithin)
{
decltype(dist) l_dist(fitWithin.first, fitWithin.second);
return l_dist(mt);
}
//change range with reference
void changeRange(const RangeInt& rng)
{
this->rng = rng;
_changeDist();
}
//the same as above but with rvalue reference
void changeRange(RangeInt&& rng)
{
std::swap(this->rng, rng);
_changeDist();
}
//set the upper bound of the range and update rng
void setUpperBound(RangeInt::TemplateParam upBound)
{
rng.second = upBound;
_changeDist();
}
//set the lower bound of the range and update rng
void setLowerBound(RangeInt::TemplateParam lowBound)
{
rng.first = lowBound;
_changeDist();
}
//copy assignment
Randomizer_RNG& operator=(const Randomizer_RNG& lhs)
{
_RETURN_IF_THIS(lhs, *this); //if (*this == lhs) return *this;
rng = lhs.rng;
changeRange(rng);
return *this;
}
//move assignment
Randomizer_RNG& operator=(Randomizer_RNG&& lhs)
{
dist = std::move(lhs.dist);
rng = std::move(lhs.rng);
mt = std::move(lhs.mt);
return *this;
}
};
typedef Randomizer_RNG<> Randomizer;
typedef Randomizer_RNG<std::mt19937> Randomizer_Twist;
};
but when I do
#include "randomizer.h"
int main()
{
game::RangeInt rngI (14, 546);
game::Randomizer rng = game::Randomizer(game::RangeInt(0, 100));
auto func = std::bind(rng, rngI);
std::cout << func();
std::cin.get();
}
it pops compiler error:
error C2512: 'game::Range<_Type>' : no appropriate default constructor available
with
[
_Type=game::uint
]
And if I try to do:
#include "randomizer.h"
int main()
{
game::RangeInt rngI (14, 546);
game::Randomizer rng = game::Randomizer(game::RangeInt(0, 100));
auto func = std::bind(&rng, rngI);
std::cout << func();
std::cin.get();
}
it says:
error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'std::_Do_call_ret<_Forced,_Ret,_Funx,_Btuple,_Ftuple>::type' (or there is no acceptable conversion)
So I wonder if Im doing something wrong or why does std::bind want default constructor from me for game::Range.
If my question is not clear or the code is not clear, let me know I will do my best.
PS: Im using Visual Studio 2012 so Variadic templates are not implemented(std::bind for instance has 378 overlaods)
Make it
Randomizer_RNG(const Randomizer_RNG& lhs)
: dist(lhs.dist), mt(lhs.mt), rng(lhs.rng)
{}
or just drop this constructor altogether: the compiler-generated one is good enough.
As written, your constructor tries to default-construct rng first, and then assign to it. But, as the compiler tells you, Range doesn't provide a default constructor.

Whats the significance of return by reference?

In C++,
function() = 10;
works if the function returns a variable by reference.
What are the use cases of it?
The commonest case is to implement things like operator[].
struct A {
int data[10];
int & operator[]( int i ) {
return data[i];
}
};
Another is to return a big object from a class via an accesor function:
struct b {
SomeBigThing big;
const SomeBigThing & MyBig() const {
return big;
}
};
in order to avoid the copying overhead.
Consider the following code, MyFunction returns a pointer to an int, and you set a value to the int.
int *i;
i = MyFunction();
*i = 10;
Now shorten that to
*(MyFunction()) = 10;
It does exactly the same thing as the first code block.
You can look at a reference as just a pointer that's always dereferenced. So if my function returned a reference - not a pointer - to an int the frist code block would become
int &i;
i = MyFunction();
i = 10;
and the second would become
MyFunction() = 10;
This is what i was looking for
Getters/setters for instance
class C
{
int some_param_;
public:
int& param() { return some_param_; }
int const& param() const { return some_param_; }
};
but here you should go with some_param being a public int. Containers provide functions that return by reference, eg. vector<T>::operator[] so that you can write v[k] = x.
A very normal use case is when you write an array like class. Here you want to overload the operator [] so as you can do a[0] = 10; In that case you would want the signature to be like int& operator[](int index);
In case you have a class that contains another structure, it can be useful to directly modify the contained structure:
struct S
{
int value;
};
class C
{
public:
S& ref() { return m_s; }
private:
S m_s;
};
Allows you to write something like:
void foo()
{
C c;
// Now you can do that:
c.ref().value = 1;
}
Note: in this example it might be more straightforward to directly make m_s public rather than returning a reference.
SO screwed up my answer
You don't even need to return a reference:
struct C { };
C f() {
return C();
}
int main() {
C a;
f() = a; // compiles fine
}
Because this behavior is quite surprising, you should normally return a const value or a const reference unless the user has a sensible intent to modify the result.
It can be usefull when implementing accessors
class Matrix
{
public:
//I skip constructor, destructor etc
int & operator ()(int row, int col)
{
return m_arr[row + col * size];
}
private:
int size;
int * m_arr;
}
Matrix m(10);
m(1,0) = 10; //assign a value to row 1, col 0
Another classic case:
class Foo {
Foo();
public:
static Foo& getSingleton();
};
std::vector has operator[] which would not allow vec[n] = m otherwise.
You can also achieve method chaining (if you so desire) using return by reference.
class A
{
public:
A& method1()
{
//do something
return *this; //return ref to the current object
}
A& method2(int i);
A& method3(float f); //other bodies omitted for brevity
};
int main()
{
A aObj;
aObj.method1().method2(5).method3(0.75);
//or use it like this, if you prefer
aObj.method1()
.method2(5)
.method3(0.75);
}
The named parameter idiom is a another use case. Consider
class Foo
{
public:
Foo(
int lions,
float tigers,
double bears,
std::string zookeeper
);
};
users of this class need to remember the position of each parameter
Foo foo( 1, 2.0, 5, "Fred" );
which can be non-obvious without looking at the header. Compared to a creator class like so
class CreateFoo
{
friend class Foo;
public:
CreateFoo();
CreateFoo& lions(int lions) {
_lions = lions;
return *this;
}
CreateFoo& tigers(float tigers) {
_tigers = tigers;
return *this;
}
CreateFoo& bears(double bears) {
_bears = bears;
return *this;
}
CreateFoo& zookeeper(const std::string& zookeeper) {
_zookeeper = zookeeper;
return *this;
}
private:
int _lions;
float _tigers;
double _bears;
std::string _zookeeper;
};
which can then be used by clients like so
Foo foo = CreateFoo().
lions(1).
tigers(2.0).
zookeeper("Fred").
bears(5)
;
assuming Foo has a constructor taking a const CreateFoo&.