Overriding operators/begin/end of a custom Array class - c++

For an exercise we have to implement an array with custom bounds in various different languages, and one of them happens to be c++. Unfortunately i have never had to deal with c++ and am now struggling to get it done. I believe i have the right "core" of the header finished. The idea is that the user specifies bounds in a template and the class fakes this with help of an inner array. We were specifically told to overwrite the [] operator and implement begin() and end() functions. I am currently stuck at the visual studio debugger saying the following:
Error C2228 left of '.end' must have class/struct/union
The gcc compiler is saying:
In file included from Aufgabe1.test.cpp:2:
array.h: In instantiation of 'typename std::__cxx11::list<T>::iterator Array<T, L, H>::begin() [with T = int; int L = -2; int H = 1; typename std::__cxx11::list<T>::iterator = std::_List_iterator<int>]':
Aufgabe1.test.cpp:16:15: required from here
array.h:29:25: error: request for member 'begin' in '((Array<int, -2, 1>*)this)->Array<int, -2, 1>::innerArray', which is of non-class type 'int [4]'
return innerArray.begin;
~~~~~~~~~~~^~~~~
array.h: In instantiation of 'typename std::__cxx11::list<T>::iterator Array<T, L, H>::end() [with T = int; int L = -2; int H = 1; typename std::__cxx11::list<T>::iterator = std::_List_iterator<int>]':
Aufgabe1.test.cpp:16:15: required from here
array.h:33:25: error: request for member 'end' in '((Array<int, -2, 1>*)this)->Array<int, -2, 1>::innerArray', which is of non-class type 'int [4]'
return innerArray.end;
~~~~~~~~~~~^~~
Simply put i have no way of continuing from here since searching for these errors bring no clarification for someone who worked primarily with java so far. How can i solve thse issues and is my implementation of this Array otherwise correct ?
EDIT:
Had to remove the code

The first error message you mention explains the problem fairly well:
Error C2228 left of '.end' must have class/struct/union
The second group of messages tells you where this occurs, specifically when you try to use innerArray.end. The thing to the left of ".end" is innerArray, which is not declared as a class, struct, or union. (It's an array of T.)
So this comes down to the fact that (C-style) arrays do not have member functions. If you need an "end" function, maybe you should look into std::array, which wraps C-style arrays in a class. (If the requirement is to overwrite certain functions instead of implement them, this is the "array" your instructor likely had in mind.)

Related

I cannot convert a '2D array whit bool' to a 'void 2D array bool'(for game of life)

When I put my functions inside the main it say that:
73 44 C:\Users\Gaia\OneDrive\Documents\Gameoflife.cpp [Error] cannot convert 'bool ()[g]' to 'bool ()[20]' for argument '1' to 'void cambiamentoMappa(bool ()[20])'
74 39 C:\Users\Gaia\OneDrive\Documents\Gameoflife.cpp [Error] cannot convert 'bool ()[g]' to 'bool ()[20]' for argument '1' to 'void ScambioMappa(bool ()[20], bool (*)[20])'
I've searched up this error but found nothing and I haven't learned how to fix this in school
It should launch and start showing the Game of Life map evolving
TL;DR: your code is ill-formed.
Your compiler accepts some ill-formed parts of your code as an extension,
but that in turn triggers other ill-formed constructs.
Your code included the following line:
const int g = 20;
Later, in the main function, your code included the following line:
int g;
The latter shadows the former.
Then you attempted to declare an array:
bool MatriceA[g][g];
In C++,
the dimension of an array shall be a constant expression.
Here, g is a variable that is not a constant expression.
Variable-length arrays are not permitted in C++.
Therefore,
your code is ill-formed.
Since you are using the Dev-C++ IDE,
you are probably using the GCC compiler.
GCC accepts variable-length arrays as an extension.
But then, you code doesn't compile either.
Your functions accept bool MatriceA[g][g] as a function parameter.
At that time, const int g = 20; is in effect.
Therefore, your function parameter is really bool MatriceA[20][20],
which is really bool (*MatriceA)[20] because of function parameter decay
(see the Stack Overflow question What is array decaying?).
Then you are calling the function with a variable-length array.
This is not allowed.
Therefore, your code is rejected.
You are calling your function cambiotoMappa with two parameters, MatriceA and MatriceB
cambiamentoMappa(MatriceA, MatriceB); /* Two actual parameters */
But your function accepts only one parameter
void cambiamentoMappa(bool MatriceA[g][g]) /* One formal parameter */

How to use decltype with member functions

I'm trying to use decltype on member functions in Visual Studio 2012. I've stumbled upon a peculiarity and I'm wondering if this is intention or if it is a compiler bug. Consider (just a code snippet without meaning to show my point):
struct Test { int f() {return 0;} } T;
std::integral_constant<decltype(T.f()), 5>;
std::integral_constant<decltype(&Test::f), 5>; // error C2440
While the second line compiles, the third gives an error C2440: 'specialization' : cannot convert from 'int' to 'int (__thiscall Test::*)(void)'
How come decltype on an instanciated call to a function yields its return type (this is what I am expecting), however trying to do the same without any member involved does yield a member function pointer? If this is the intended behavior, what is the reasoning behind it? How would I denote that I'm requesting the return type of a member function, without actually having an instance at hand? Of course I could do it the dirty way:
std::integral_constant<decltype(((Test*)nullptr)->f()), 5>;
But unquestionable this is pretty, pretty ugly and there should be a clean, straightforward C++ way to express this.
&Test::f does not call the member function Test::f. Instead, it takes the address of the member function and results in a pointer to member function, which is of type int (Test::*)().
In order to do what you want, you should use std::declval. The correct syntax is
std::integral_constant<decltype(std::declval<Test>().f()), 5>

error: use of overloaded operator '*' is ambiguous

When I try to compile this source in c++:
void ParticleSystem::setState(std::vector<Vec2f>& statesVector)
{
std::vector<Vec2f> pState(2);
for (int i = 0; i < 2*np; i += 2) {
pState[0] = *statesVector[i];
pState[1] = *(statesVector[i+1]);
(*particles[i/2]).setState(pState);
}
}
I get the following error:
ParticleSystem.cpp:110:15: error: use of overloaded operator '*' is ambiguous (operand type
'value_type' (aka 'gfx::TVec2<float>'))
pState[0] = *statesVector[i];
^~~~~~~~~~~~~~~~
ParticleSystem.cpp:110:15: note: built-in candidate operator*(float *)
ParticleSystem.cpp:110:15: note: built-in candidate operator*(const float *)
ParticleSystem.cpp:111:15: error: use of overloaded operator '*' is ambiguous (operand type
'value_type' (aka 'gfx::TVec2<float>'))
pState[1] = *(statesVector[i+1]);
I have look for the error already in the forums and followed some steps but i never get to make it work. Moreover, I've also tried to understand the explanation in the notes of the error, but I cannot.
I really hope someone can help me.
Finally, if someone rates this question negatively, at least explain why, please.
The problem is that you didn't understand the syntax that comes with references. While you do declare a reference with &, you use it as you would use the actual variable and not like a pointer, which means you can't use the operator * on it (unless it's a reference on a pointer type). Using the * operator produces the same effects as if you were to use it on a regular variable.
You can fix your problem by removing the * in your code like this:
pState[0] = statesVector[i];
pState[1] = statesVector[i+1];
particles[i/2].setState(pState);
Your code could compile as is if you defined operator* in the Vec2f class and made it return a Vec2f. However, this make little sense in a semantics point of view (a dereferenced value should not give something of the same type) so this is not the way to fix your problem.

What does this mean: "warning: comparison between 'enum A<B>' and 'enum A<B>'"?

I added following at line 42 of proto.h:
typedef boost::make_unsigned<off_t>::type uoff_t;
And now I get this verbose and confusing warning from gcc complaining about comparing an enum to the same enum type:
In file included from proto.cpp:12:
/usr/local/include/boost/type_traits/is_unsigned.hpp: In instantiation of 'boost::detail::is_ununsigned_helper<long int>':
/usr/local/include/boost/type_traits/is_unsigned.hpp:73: instantiated from 'boost::detail::is_unsigned_imp<long int>'
/usr/local/include/boost/type_traits/is_unsigned.hpp:123: instantiated from 'boost::is_unsigned<long int>'
/usr/local/include/boost/type_traits/make_unsigned.hpp:110: instantiated from 'boost::detail::make_unsigned_imp<long int>'
/usr/local/include/boost/type_traits/make_unsigned.hpp:130: instantiated from 'boost::make_unsigned<long int>'
proto.h:42: instantiated from here
/usr/local/include/boost/type_traits/is_unsigned.hpp:40: warning: comparison between 'enum boost::detail::is_unsigned_values<long int>::<anonymous>' and 'enum boost::detail::is_unsigned_values<long int>::<anonymous>'
Can anyone decipher this?
This is what happens
BOOST_NO_INCLASS_MEMBER_INITIALIZATION gets defined in Boost.Config (not sure why it would for gcc, but I'll leave that alone for the moment). Thus,
BOOST_STATIC_CONSTANT(no_cv_t, minus_one = (static_cast<no_cv_t>(-1)));
BOOST_STATIC_CONSTANT(no_cv_t, zero = (static_cast<no_cv_t>(0)));
declarations in boost::detail::is_unsigned_values get expanded to
enum { minus_one = (static_cast<no_cv_t>(-1)) };
enum { zero = (static_cast<no_cv_t>(0)) };
then these two enumerators of unnamed but different enumerations get compared in boost::detail::is_ununsigned_helper. Hence the warning, which wouldn't have happened if BOOST_STATIC_CONSTANT() were expanded to static const no_cv_t blah blah....
There are two questions left to be answered:
-> Why does BOOST_NO_INCLASS_MEMBER_INITIALIZATION get defined in your case?
-> If that macro does get defined, such a warning (comparison of enumerators of different enums) can be produced. It's harmless here, yet it might be nice to be prevented in Boost. Is that worth it?
Note: I used Boost 1.43's code for reference.

C++ iterator problems

I have the following member data
vector<State<T>*> activeChildren;
I want to clean-up these pointers in my destructor
StateContainer<T>::~StateContainer() {
vector<State<T>*>::iterator it =
activeChildren.begin();
while(it!=activeChildren.end()) {
State<T>* ptr = *it;
it = activeChildren.erase(it);
delete ptr;
}
}
I get the following error from g++ 4.3.2 on Ubuntu:
./fsm2/StateContainer.cpp: In destructor ‘virtual ervan::StateContainer<T>::~StateContainer()’:
../fsm2/StateContainer.cpp:24: error: expected `;' before ‘it’
../fsm2/StateContainer.cpp:25: error: ‘it’ was not declared in this scope
Can anyone tell me what I've done wrong? I get this error in two more places where I use iterator loops, but not when I use for_each(...)
Looks like typename time again - I think you need:
typename vector<State<T>*>::iterator it = ...
A heuristic for g++ users - when you see this message in template code:
expected `;' before ‘it’
it is a pretty good bet that the thing in front of the 'it' is not being seen by the compiler as a type and so needs a 'typename' added.
It's a parsing issue. In this code, vector<State<T>*>::iterator is a nested dependent type.
Until you know what T is (and T isn't known at parse time), the parser/compiler doesn't realize that iterator is a type (could be a static member variable, for all it knows).
Therefore, you must prefix the definition with typename as a hint to tell the compiler that for all vector<State<T>*>, vector<State<T>*>::iterator is a type name.