Unfortunately I still got a problem with my templated code from here:
C++ fancy template code problem
on line 49 in the file 'utility':
error C2440: 'Initializing': cannot convert from 'const int' to 'IntersectionData *'
error C2439: 'std::pair<_Ty1,_Ty2>::second': member could not be initialized
how could i figure out where the problem is? the only place i use a pair with 'IntersectionData*' is here:
#include "MRMaterialMatth.h"
#include "IntersectionData.h"
using namespace std;
struct IShaderMatth {
virtual ~IShaderMatth() {}
vector<pair<MaterialMatth,IntersectionData*> > traceCols;
};
and there are not any other compiler errors
how can I track down this?
//edit: utility is not my code. it must be from std.. the code of line 49 looks like this:
template<class _Other1,
class _Other2>
pair(const pair<_Other1, _Other2>& _Right)
: first(_Right.first), second(_Right.second)
{ // construct from compatible pair
}
line 49 is the line of the comment
edit2:
the only places where i change something about the content of tracecols look like this:
IntersectionData* iDataOut = NULL;
if(newIData_out!=NULL)
{
iDataOut = new IntersectionData(*iData);
}
traceCols->push_back(make_pair(MaterialMatth(),iDataOut));
and
if(traceCols){
traceCols->push_back(make_pair(MaterialMatth(), NULL));
}
and
if(traceCols)
{
(*traceCols)[traceCols->size()].second = new IntersectionData(*newIData);
}
is NULL the problem? it's a pointer, so i should be allowed to create a pair with NULL, no??
Try explicitly casting the NULL to IntersectionData * in your call to make_pair().
if(traceCols){
traceCols->push_back(make_pair(MaterialMatth(), (IntersectionData *)NULL));
}
There is a problem initializing one of those pairs.
Ask yourself, "What initializes that?"
The answer is the vector traceCols.
Now ask, "Where am I creating elements in traceCols?"
Once you answer that, you should know what is going wrong.
Watch out for the line (*traceCols)[traceCols->size()].second = new IntersectionData(*newIData) - it seems like that would go out of the vector's bounds (since the largest index of a vector is size() - 1).
I'm not sure if the NULL is causing it - so comment out that line, and see for yourself (or try Dave's suggestion)! If it doesn't work, comment out another. Eventually, you'll either find what line, and be able to ask a more specific question, or it'll be none of those things, and you'll know you have to search somewhere else. That's what I do when I see all these silly compiler error messages.
It looks like you have an assignment somewhere from a pair<MaterialMatth,int>. The compiler is trying to convert from that to the declaration you listed, but it can't convert from an int to a pointer without an explicit cast.
Related
I have my little code that needs to be solved/fixed but I'm struggling and getting stuck on problems too simple to be found with a simple Google search.
int vector, Shape, Shapes;
int Parameters;
int main()
{
string UserCommand;
vector <Shape*> Shapes;
vector <string> Parameters;
}
My question is what basically the <> around the pointer are for? What do they do? They give me the following error on <Shape*>:
expected an expression
Is something meant to follow this pointer?
Also, where vector <string> Parameters; is, I get the error:
type name not allowed
It's something to do with the <> symbols again.
What does one do when something is surrounded by <>?
FOUND THE ISSUE. I simply created another header and cpp file, then deleted them both and visual studio woke up and removed the error. Weird
I have a header file defining some parameters. I have defined some of the parameters as extern. My program works fine with other data types such as double and int, except when I try to add vector variables. The declaration in header file is
extern std::vector<double> my_vec;
In my main file, I am constructing the vector using this code:
std::vector<double> my_vec(3,0);
When I try to clear the vector using the clear method, the compiler is giving an error saying that unknown type. I am not even sure how to debug this. Can someone help?
P.S. I was originally trying to assign some values to this vector using:
my_vec[0] = 1;
but the compiler says that C++ requires a type specifier for all declarations. I googled this error, but I don't understand because I am specifying the type of my_vec.
Edit: example:
main.cpp
#include "params.h"
#include <vector>
std::vector<double> my_vec(3,0);
my_vec.clear();
// edit: my_vec[0] = 1; this also produces an error
int main(){
return 0;
}
params.h
#include <vector>
extern std::vector<double> my_vec;
Error message:
main.cpp:6:1: error: unknown type name 'my_vec'
my_vec.clear();
^
main.cpp:6:7: error: cannot use dot operator on a type
my_vec.clear();
^
2 errors generated.
You can't execute statements outside of a function - which is what you're trying to do with my_vec.clear();. It doesn't matter that clear() is a method of the vector class - invoking a method (as opposed to constructing a variable) is a statement, just like x = 1; . Those belong in functions.
You have to put your statement somewhere in your main(), e.g.:
int main(){
my_vec.clear();
return 0;
}
or make sure and construct my_vec the way you want it to look like, to begin with.
Also, more generally, you should avoid global variables if you don't really need them. And - you very rarely do. See:
Are global variables bad?
Edit: OP asks whether we can get around this restriction somehow. First - you really shouldn't (see what I just said). But it is possible: We can use a static block, which is implementable in C++, sort of.
i created an account so i can get some help with stacks in STL , i need to write a function that takes stack as a parameter and swaps the first element with the last element , i searched the site for some help i found one :"https://stackoverflow.com/a/36188943/9990214" , i tried the same thing , but i keep getting this error : expression must have a constant value with red line under "int tmp[sz-1];".
it keeps giving me the error before reaching the main , any help would be appreciated , keep in mind am trying to write the function using STL.
ps : i tried replying with a comment to the person who answered the question but it's not allowing me to do that because i need 50 reputation.
using namespace std;
void rev(stack<int>&x){
int sz=x.size(),mytop,mybottom;
mytop=x.top();
x.pop();
int tmp[sz-1],i=0;
while(!x.empty()){
mybottom=x.top();
tmp[i++]=mybottom;
x.pop();
}
stack<int> returnIt;
returnIt.push(mybottom);
for(i=0;i<=sz-3;i++){
returnIt.push(tmp[i]);
}
returnIt.push(mytop);
while(!returnIt.empty()){
int tt=returnIt.top();
x.push(tt);
returnIt.pop();
}
}
The reason you're getting an error is that variable-length arrays are not a part of standard C++. This matters for your definition of tmp:
int tmp[sz-1], i=0; //sz is not known at compile-time, therefore, this is invalid code
Some compilers will allow code like this by allowing VLA's, but not being standard, you should use a different solution. Usually, for tasks like this, std::vector is ideal:
std::vector<int> tmp(sz - 1);
int i = 0;
This should compile (so long as you #include<vector> alongside your other includes), and should have the behavior you expect from your code.
I have a C++ class; this class is as follows:
First, the header:
class PageTableEntry {
public:
PageTableEntry(bool modified = true);
virtual ~PageTableEntry();
bool modified();
void setModified(bool modified);
private:
PageTableEntry(PageTableEntry &existing);
PageTableEntry &operator=(PageTableEntry &rhs);
bool _modified;
};
And the .cpp file
#include "PageTableEntry.h"
PageTableEntry::PageTableEntry(bool modified) {
_modified = modified;
}
PageTableEntry::~PageTableEntry() {}
bool PageTableEntry::modified() {
return _modified;
}
void PageTableEntry::setModified(bool modified) {
_modified = modified;
}
I set a breakpoint on all 3 lines in the .cpp file involving _modified so I can see exactly where they are being set/changed/read. The sequence goes as follows:
Breakpoint in constructor is triggered. _modified variable is confirmed to be set to true
Breakpoint in accessor is triggered. _modified variable is FALSE!
This occurs with every instance of PageTableEntry. The class itself is not changing the variable - something else is. Unfortunately, I don't know what. The class is created dynamically using new and is passed around (as pointers) to various STL structures, including a vector and a map. The mutator is never called by my own code (I haven't gotten to that point yet) and the STL structures shouldn't be able to, and since the breakpoint is never called on the mutator I can only assume that they aren't.
Clearly there's some "gotcha" where private variables can, under certain circumstances, be changed without going through the class's mutator, triggered by who-knows-what situation, but I can't imagine what it could be. Any thoughts?
UPDATE:
The value of this at each stage:
Constructor 1: 0x100100210
Constructor 2: 0x100100400
Accessor 1: 0x1001003f0
Accessor 2: 0x100100440
UPDATE2:
(code showing where PageTableEntry is accessed)
// In constructor:
_tableEntries = std::map<unsigned int, PageTableEntry *>();
// To get an entry in the table (body of testAddr() function, address is an unsigned int:
std::map<unsigned int, PageTableEntry *>::iterator it;
it = _tableEntries.find(address);
if (it == _tableEntries.end()) {
return NULL;
}
return (PageTableEntry *)&(*it);
// To create a new entry:
PageTableEntry *entry = testAddr(address);
if (!entry) {
entry = new PageTableEntry(_currentProcessID, 0, true, kStorageTypeDoesNotExist);
_tableEntries.insert(std::pair<unsigned int, PageTableEntry *>(address, entry));
}
Those are the only points at which PageTableEntry objects are stored and retrieved from STL structures in order to cause the issue. All other functions utilize the testAddr() function to retrieve entries.
UNRELATED: Since C++ now has 65663 questions, and so far 164 have been asked today, that means that only just today the number of C++ tagged questions exceeded a 16-bit unsigned integer. Useful? No. Interesting? Yes. :)
Either your debugger isn't reporting the value correctly (not unheard of, and even expected in optimized builds) or you have memory corruption elsewhere in your program. The code you've shown is more-or-less fine and should behave as you expect.
EDIT corresponding to your 'UPDATE2':
The problem is in this line:
return (PageTableEntry *)&(*it);
The type of *it is std::pair<unsigned const, PageTableEntry*>&, so you're effectively reinterpret-casting a std::pair<unsigned const, PageTableEntry*>* to a PageTableEntry*. Change that line to:
return it->second;
Keep an eye out for other casts in your codebase. Needing a cast in the first place is a code smell, and the result of doing a cast incorrectly can be undefined behavior, including manifesting as memory corruption as you're seeing here. Using C++-style casts instead of C-style casts makes it trivial to find where casts occur in your codebase so they can be reviewed easily (hint, hint).
std::map<>::find() returns an iterator which when dereferenced returns a std::map<>::value_type. The value_type in this case is a std::pair<>. You're returning the address of that pair rather than the PageTableEntry. I believe you want the following:
// To get an entry in the table (body of testAddr() function, address is an unsigned int:
std::map<unsigned int, PageTableEntry *>::iterator it;
it = _tableEntries.find(address);
if (it == _tableEntries.end()) {
return NULL;
}
return (*it).second;
P.S.: C-style casts are evil. The compiler would have issued a diagnostic with a C++ cast in place. :)
Try looking at the value of this at each breakpoint.
That copy constructor and assignment operator are both going to be used a lot if you're using STL containers. Maybe if you show us the code for those, we would see something wrong.
Could you add another unique value to the class to track the PageTableEntry s?
I know that I've had problems like this where the real problem was that there were multiple entries that looked the same and the breakpoints might switch PageTableEntry s without me realizing it.
My code that I have is quite large and complicated so I won't waste your time reading it, but you're going to have to make certain assumtions about variables in it as a result. I will tell you the values of the variables which I have confirmed in the debugger so you know with certainty. Know that I have omitted a lot of unrelated code in here so what you see isn't everything but I have included everything that is relevant.
// This is defined in a class:
char**** m_DataKeys;
// This is in a member function of the same class:
m_DataKeys = new char*** [m_iNumOfHeroes]; // m_iNumOfHeroes = 2
while ( pkvHero )
{
// iHeroNum = 0 and then 1 #define NUM_OF_ABILITIES 4
m_DataKeys[iHeroNum] = new char** [NUM_OF_ABILITIES];
for (int ability = 0; ability < NUM_OF_ABILITIES; ability++)
{
if (pkvExtraData) // only is true when iHeroNum == 1 and ability == 0
{
// iNumOfExtraData == 2
m_DataKeys[iHeroNum][ability] = new char* [iNumOfExtraData];
while ( pkvSubKey )
{
// iCurExtraDataNum increments from 0 to 2
m_DataKeys[iHeroNum][ability][iCurExtraDataNum] = new char [50];
I put a break point on the line
m_DataKeys[iHeroNum] = new char** [NUM_OF_ABILITIES];
Before the line is called and when iHeroNum == 0 the m_DataKeys array looks like:
m_DataKeys | 0x02072a60
pointer | 0xffeeffee
Error : expression cannot be evaluated
Which is expected. After the line gets called it looks like:
m_DataKeys | 0x02072a60
pointer | 0x02496b00
pointer | 0xffeeffee
Error : expression cannot be evaluated
Which seems to look correct. However, since I set a breakpoint there, I hit play and had it hit it on the next loop around, where iHeroNum == 1 now and ran the line and m_DataKeys then looked like this:
m_DataKeys | 0x02072a60
pointer | 0x02496b00
pointer | 0xffeeffee
Error : expression cannot be evaluated
Which is the exact same as before! The line didn't change the array.... At all!
For clarification, m_DataKeys is a 3 dimensional array of character pointers to character arrays of size 50.
I can't figure out why this is happening, it looks like my code is correct. Is it possible that the garbage collector is screwing me over here? Or maybe the new allocator?
Edit: A Symptom of a Larger Problem
Let me elaborate a little more on the structure of my code, because really, this is just a cheap solution to a bigger problem.
I already have structs as one of you wisely suggested:
struct HeroData
{
// Lots o data here
// ...
// .
//
AbilityData* Abilities[NUM_OF_ABILITIES];
}
struct AbilityData
{
// More data here
// ...
// .
CUtlMap<char*,int> ExtraData [MAX_ABILITY_LEVELS];
}
Now when it got complicated and I had to do this DataKeys arrays of pointers to arrays of pointers crap is only when the need arose to be loading in some data to a dynamic structure, where both the keys, the values, and the numbers of data are completely dynamic. So I thought to use a map of char arrays to ints, but the only problem is that I can't store the actual char array in my map, I have to use a char *. I tried defining the map as:
CUtlMap<char[50],int> ExtraData [MAX_ABILITY_LEVELS];
But that really didn't work and it seems sort of strange to me anyway. So, I had to find some place to stick all these ExtraDataKeys and for some reason I thought it cool to do it like this. How can I store char arrays in objects like arrays or maps?
Since you are using pointers as class members, my best guess is that you are violating The Rule Of Three. That is, you did not provide a copy constructor and a copy assignment operator for your class. That usually leads to strange data loss when passing objects of your class around.
Note that no sane C++ programmer would use char****. Here is my best attempt to fix your problem using vectors and strings, but there is probably a much better design for your specific problem:
#include <string>
#include <vector>
class Foo
{
int m_iNumOfHeroes;
std::vector<std::vector<std::vector<std::string> > > m_DataKeys;
enum { NUM_OF_ABILITIES = 4, iNumOfExtraData = 2 };
public:
explicit Foo(int iNumOfHeroes)
: m_iNumOfHeroes(iNumOfHeroes)
, m_DataKeys(m_iNumOfHeroes, std::vector<std::vector<std::string> >
(NUM_OF_ABILITIES, std::vector<std::string>(iNumOfExtraData)))
{
}
};
int main()
{
Foo x(2);
}
In case you have never seen that colon syntax in the constructor before, that is a member initializer list.
I really wish C++ had array bounds checking
std::vector and std::string do have bounds checking if you use the foo.at(i) syntax instead of foo[i]. In Debug mode, even foo[i] has bounds checking enabled in Visual C++, IIRC.
Though the code might be correct, I personally find that working with something like a char **** can get pretty confusing pretty fast.
This is just my personal preference, but I always try to organize things in the most clear and unambiguous way I can, so what I would do in your situation would be something like
struct Ability
{
char extraData[NUM_OF_EXTRA_DATA][50];
};
struct HeroData
{
Ability abilities[NUM_OF_ABILITIES];
};
class Foo
{
// here you can choose a
HeroData *heroArray;
// and then you would alloc it with "heroArray = new HeroData[m_iNumOfHeroes];"
// or you can more simply go with a
std::vector<HeroData> heroVector;
};
I think this makes things more clear, making it easier for you and other programmers working on that code to keep track of what is what inside your arrays.
I think you expect the wrong thing to happen (that the visual display in the debugger would change), even though your code seems correct.
Your debugger displays m_DataKeys, *m_DataKeys and **m_DataKeys, which is the same as m_DataKeys, m_DataKeys[0] and m_DataKeys[0][0]. When you change m_DataKeys[1], you are not going to notice it in your debugger output.
The following might help you: in my debugger (MS Visual Studio 2005), if you enter e.g. m_DataKeys,5 as your watch expression, you will see the first 5 elements of the array, that is, m_DataKeys[0], m_DataKeys[1], ..., m_DataKeys[4] - arranged in a neat table. If this syntax (with the ,5) doesn't work for you, just add m_DataKeys[1] into the debugger's watch window.
Not sure why this didn't occur to me last night, but I was pretty tired. Heres what I decided to do:
struct AbilityData
{
// Stuff
CUtlMap<char*,int> ExtraData [MAX_ABILITY_LEVELS];
char **DataKeys;
}
Thats what my abilityData struct now looks like, and it now works, but now I want to reorganize it to be like:
struct AbilityData
{
// Stuff
CUtlMap<char*,int[MAX_ABILITY_LEVELS]> ExtraData;
char **DataKeys;
}
Because it makes more sense that way, but then I run into the same problem that I had before with the char array. It almost seems like to me it might just be best to ditch the whole map idea and make it like:
struct AbilityData
{
// Stuff
int *ExtraData;
char **DataKeys;
}
Where ExtraData is now also a dynamically allocated array.
The only problem with that is that I now have to get my data via a function which will loop through all the DataKeys, find a matching key for my input string, then return the ExtraData associated with it.