Yet Another: Passing Vector of Structs to Function - C++, MinGW - c++

I am aware there are numerous similar queries on here, however I haven't been able to resolve this, not has a colleague, so:
I am using MinGW (4.8.x) with Eclipse CDT Kepler.
1) I have my own code and to clean it up I changed it to use a vector of structs - all is fine, except that the function that receives it complains about Invalid Argument'.
2) I reduced my code down to a minimum working example, if I place it all in a single file it works, however if I move out my definitions to the header (which I need to do in my main code) it suddenly cannot resolve the fields in the struct...
The code below is for a three file configuration, header/function/main.
(In my main code I use namespace std - but that doesn't seem to be the problem. Also, there are extraneous headers for a minimum working example in this, however they are needed in my main code.)
myheaders.h
/*************************/
/****** myheaders.h ******/
/*************************/
/**-- Header Files --**/
// File Streams and IO
#include <stdio.h>
#include <sstream>
#include <iostream>
#include <fstream>
// For strtod -> string to double
#include <stdlib.h>
// Math Operations
//#include <math.h>
#include <cmath>
// To get the CPU time
#include <time.h>
// For Vectors
#include <vector>
// For strings, C strings right now...
#include <cstring>
// Needed globally for the function definitions
// using namespace std;
#ifndef MY_HEADERS
#define MY_HEADERS
struct SpeciesLoss {
int ReactionID;
int SpeciesID;
double coefficient;
};
std::vector< double > SpeciesLossRate(std::vector<SpeciesLoss> , int, const std::vector< double > & );
#endif
function.cpp
/*************************/
/****** function.cpp *****/
/*************************/
#include "myheaders.h"
std::vector< double > SpeciesLossRate(
std::vector< SpeciesLoss > SpeciesLossList,
int Number_Species,
const std::vector< double >& Combined_Rates
)
{
std::vector< double > temp_species_loss;
temp_species_loss.resize(1);
temp_species_loss[0]=SpeciesLossList[0].ReactionID;
return temp_species_loss;
}
main.cpp
/*************************/
/******** main.cpp *******/
/*************************/
#include "myheaders.h"
std::vector< SpeciesLoss > SpeciesLossAll; // New vector for recording species loss, uses a vector of structs
int main(int argc, char* argv[])
{
std::vector< double > Rates;
Rates.push_back(1);
SpeciesLossAll.push_back(SpeciesLoss());
SpeciesLossAll[0].ReactionID = 0;
SpeciesLossAll[0].SpeciesID = 0;
SpeciesLossAll[0].coefficient = 0;
std::vector< double > SpeciesConcentrationChange = SpeciesLossRate(SpeciesLossAll,1, Rates);
return 0;
}
Edit:
Screenshot
Edit 2:
And interesting update - it compiles fine on Linux with GCC. Better than nothing, but I still want to know what is going wrong, plus I'd like my code to be cross platform...
Edit 3:
This is more and more bizarre - I just tested my code (the full project that compiles on Linux) on my home PC which runs Windows 7 where it builds fine while my laptop runs Windows 8 and the problem occurs.
The Settings for the C++ build are absolutely identical.
Both run MinGW 4.8.1...
Both run the latest Eclipse Kepler...
And yes, I am aware that I need to test some suggestions still.

#ifndef MY_HEADERS
#define MY_HEADERS
Should be at the beginning of your file. Since you have no idea in what order the compiler is going to include headers this might be causing a problem... Especially if you are including your personal header in multiple files, wich will definitely make it behave like so. Also, keep in mind that since you are not providing a default constructor but rather using the one the compiler provides for you, those variables inside the struct will most likely not be initialized to zero as you expect them.
EDIT#1
Are you compiling everything NOT just main... I just copied your code into VS and it works!
EDIT#2
Try defining the function inline instead of a separate implementation file.
static std::vector< double > SpeciesLossRate(
std::vector< SpeciesLoss > SpeciesLossList,
int Number_Species,
const std::vector< double >& Combined_Rates
)
{
std::vector< double > temp_species_loss;
temp_species_loss.resize(1);
temp_species_loss[0]=SpeciesLossList[0].ReactionID;
return temp_species_loss;
}
EDIT#3
Ok, from the screen-shot this is definitely valid code. For sake of trying everything; implement your own constructor and copy constructor of the struct. I know this might sound silly but maybe Eclipse doesn't think so.

OK - I have found the answer - I think - and it boils down to Eclipse.
-> Project -> C/C++ Index -> Rebuild
This resolves the issue.
In fact, this problem is known on earlier Eclipse CDT versions: https://bugs.eclipse.org/bugs/show_bug.cgi?id=348170

Related

When I split up my C++ class into a header and implementation I get 20 compiler errors which don't make sense

I was splitting up my program into a header and implementation file per usual, however, when I tried to run the code, I got a ton of compile errors. This seems to be an issue with my computer or IDE, but I have not seen it before. This should be relatively simple as it is for a class project.
The code is as follows:
colorPicker.h
#pragma once
class colorPicker {
private:
string colorArray[7];
public:
colorPicker();
void printAllColors();
string randomColor();
};
colorPicker.cpp
#include "colorPicker.h"
#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
colorPicker::colorPicker() {
colorArray[0] = "Red";
colorArray[1] = "Green";
colorArray[2] = "Purple";
colorArray[3] = "Yellow";
colorArray[4] = "Orange";
colorArray[5] = "Indigo";
colorArray[6] = "Pink";
}
void colorPicker::printAllColors() {
for (int i = 0; i < 7; i++) {
cout << colorArray[i] << endl;
}
}
string colorPicker::randomColor() {
srand((unsigned)time(0));
int j = 0;
j = rand() % 7;
return colorArray[j];
}
main.cpp
#include "colorPicker.h"
#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main() {
colorPicker p;
p.printAllColors();
cout << "Random Color: " << p.randomColor() << endl;
system("pause");
return 0;
}
There are 20 errors given by the compiler, however, they all seem to be stemming from two undeclared identifiers which are most definitely declared. I am at a loss for what I could possibly do to fix it, and this project is due Sunday. Thank you.
Here are the errors
Tons of Errors
You need #include "colorPicker.h" in colorPicker.cpp. Each .cpp file is handled basically independently by the compiler and they are all joined at the end by the "linker." When the compiler looks at colorPicker.cpp without an include of the corresponding header, it's at a loss as to the definition of all the classes you're working with.
There are a few things you are doing wrong. I'll just pick on a couple.
Firstly, each header file you write should be self-contained - in the sense that, if it relies on content of some other headers, it includes that header. If a compilation unit (a formal name for a source file with a .cpp in your case) includes your header, it should not have to include something else your header depends on.
Second, it is a bad idea for a header to rely on any using directive, such as using namespace std. There are plenty of explanations of that available, so I won't repeat.
To understand the above, look at colorPicker.h
class colorPicker {
private:
string colorArray[7];
public:
colorPicker();
void printAllColors();
string randomColor();
};
Firstly, this depends on string, but there is no definition of string visible in the header file. Usage of that type depends on the standard header <string>.
Second, that string type is within namespace std. So your header relies on the compilation unit (the source file that includes your header) having previously used a using directive i.e. using namespace std.
To fix these two problems, change the header to
#ifndef SOME_MACRO_UNIQUE_TO_YOUR_COLOR_PICKER_HEADER
#define SOME_MACRO_UNIQUE_TO_YOUR_COLOR_PICKER_HEADER
#include <string>
class colorPicker
{
private:
std::string colorArray[7];
public:
colorPicker();
void printAllColors();
std::string randomColor();
};
#endif
(I've also done some minor changes of layout, since I have various reasons to prefer that.
However, the #include <string> means that this version will not fail to compile, as yours does, if it is included by a compilation unit that does not have #include <string>.
The usage of the fully qualified name std::string, rather than string, also means there is no dependence on the using directive using namespace std. It also means compilation errors can't be triggered in your header if your compilation unit has another using directive.
I've also used an include guard, rather than #pragma once. Although most modern compilers support #pragma once, it is actually not standard C++ (a #pragma, by definition in the standard, is a compiler-specific hook). Include guards are supported in standard C++.
If you've done that, your code should mostly compile as is. However, optionally, you may wish to
remove the using directives using namespace std from your other files. If you do that, you will need to change the definition of colorPicker::randomColor() in colorPicker.cpp so it returns the fully qualified type std::string rather than string.
Remove #include <string> from files that have #include "colorPicker.h". This is possible, since colorPicker.h now includes <string>. This step is optional, since there is no problem with including standard headers more than once in a compilation unit.
A few other notes
In C++, although it is not a major concern, it is usually considered better to use include <cstdio> and <cstdlib> rather than the C headers <stdio.h> and <stdlib.h>.
Your code is calling srand((unsigned)time(0)) whenever colorPicker::randomColor() is called. It is better to only call it once in an entire program, not in a function that may be called multiple times.
A header file should be self-contained as far as #includes go. That means that you should be able to #include the header file without having to include other stuff before it!
Your colorPicker.h does not meet that requirement. It apparently uses std::string from the standard library but does not have an #include <string> on top, so everyone who uses colorPicker.h has to remember to put an #include <string> before it. That's pretty annoying.
Even worse, colorPicker.h refers to std::string as string, which implies a using std::string; or using namespace std; somewhere before any #include "colorPicker.h" line, and both of those are very bad coding style in C++, if not used in tighter scopes.
Here's how to fix the header file:
#pragma once
#include <string>
class colorPicker {
private:
std::string colorArray[7];
public:
colorPicker();
void printAllColors();
std::string randomColor();
};
As far as your *.cpp files go, I can see that you are using #include "stdafx.h". Why? It's a non-standard Microsoft thing completely unnecessary in your case. You are also using it incorrectly. It must be the first include. Just remove it entirely.
Some other suggested cleanup:
using namespace std; lines in *.cpp files is not as bad as in header files, but if I were you, I'd just get rid of it completely. Just use complete names. Say std::cout, not cout. And so on. It's just the most consistent way and it avoids a lot of trouble.
You include a lot of headers which you don't need. For example, what's <ctime> for?
Don't use system("pause");. Do not look for artificial ways of pausing a command-line program.
You may need add head file and in colorPicker.h.
And the std namespace is needed while using string.
BTW, the header guards is recommended strongly.
#ifndef COLOR_PICKER_H
#define COLOR_PICKER_H
#pragma once
#include <string>
class colorPicker {
private:
std::string colorArray[7];
public:
colorPicker();
void printAllColors();
std::string randomColor();
};
#endif

Eclipse CDT can't resolve a structs function when accessed from a std::map

The situation is as follows: I declare a struct in a header file, and in the accompanying source file I put instances of this struct in a std::map<int, myStruct>.
The code compiles and runs fine, but Eclipse does'nt recognize the function call and keeps it underlined red (can not open declaration either).
Example code:
//myClass.h
struct myStruct{
int returnValue(){
return 4;
}
};
// other class parameters here
and in the source
//myClass.cpp
#include "myClass.h"
#include <iostream>
#include <map>
using std::map;
int main(){
//create map with struct and assign
map<int, myStruct> myMap;
myStruct exampleStruct;
myMap[3]=exampleStruct;
//access struct via [] map operator
std::cout << myMap[3].returnValue() << "\n"; //this line flagged by Eclipse, but works
return 0;
}
Is this behavior of Eclipse known, or is my config wrong?
Also, on a side note, I am not a professional progammer, so style advice etc is very welcome :)
EDIT: fixed typos in myClass.h and myClass.cpp
After fixing typos, the code is fine and is accepted without even a warning. So I only imagine that it could be a problem in Eclipse configuration.
Okay, this is embarrassing. I ran the sample code through eclipse (the real example is very long and depends on some custom libraries) and Eclipse had no issue with the function of the struct inside the map.
So I rebuilt the index of the real project, and now everything is fine. Strange, because Eclipse always seemed to update the index when I created a new class, but not this time... so thanks to all who read and answered, but the problem is solved already.

Sanity of Headers

I'm just starting to teach C++, coming from some other languages. I am wishing there were some way to consistently check the API created by a (student) file.
Suppose a student submits this file:
// this is stu.cpp
#include <iostream>
using namespace std;
double x(int y) {return y+0.5;}
Actually, suppose I asked the student to define some other function int x(int). I would like to be able to check this by running this code:
// this is stu.h
int x(int);
// this is gra.cpp
#include "stu.h"
#include <iostream>
using namespace std;
int main() {
cout << x(0); // test their code
}
So I am trying to see if the student's implementation matched the required interface, and testing it on input 0. I would have hoped this would not compile. But when I do
g++ -Wall -Wconversion *.cpp -o gra
./gra
It compiles and runs without crashing, giving output 0. This remains true even if I compile the two files separately and link them after.
I know that nm doesn't list return types. Is that the same reason that we can link together two files when the return values don't match? Is there any sane way to test this? (Like are there compile-time typeof assertions?)
Or is this a specific bug because of int and double being interconvertible? Are there additionall compiler options that could catch this?
Instead of compiling the student's code separately, why don't you just include it directly in your tester program?
int x(int);
#include <stu.cpp>
Then you should get a nice error like this:
a.cpp:2:8: error: functions that differ only in their return type cannot be overloaded
While this is not the "normal" way to compile a student's code, it guarantees that the code can be checked.
Alternatively, you may use a compiler command-line option like -include (GCC, Clang) to force the compiler to include a header file containing your desired API when compiling the student's C++ file. As an example:
api.h
int x(int);
compile with g++ stu.cpp -include api.h, and the appropriate error will be raised.
You can do the following:
// this is gra.cpp
#include "stu.h"
#include "stu.cpp"
#include <iostream>
using namespace std;
int main() {
cout << x(0); // test their code
}
And compile only gra.cpp of course.

Undefined reference to 'Class::Class'

After fixing the previous problem (see my one other question that I have asked). I had declared more classes.
One of these is called CombatAdmin which does various things: (Header file)
#ifndef COMBATADMIN_H
#define COMBATADMIN_H
#include <string> // Need this line or it complains
#include <Player.h>
#include <Sound.h>
#include <Enemy.h>
#include <Narrator.h>
using namespace std;
class Enemy;
class Player;
class CombatAdmin // Code yet to be commented here, will come soon.
{
public:
CombatAdmin();
void healthSet(double newHealth, string playerName);
void comAdSay(string sayWhat);
void playerFindsChest(Player *player,Weapon *weapon,Armour *armour);
void youStoleOurStuffEncounter(Player *player);
void comAdWarning(string enemyName);
void comAdAtkNote(string attack, double damage,string target,string aggresor);
void entDefeated(string entName);
void comAdStateEntHp(string ent, double hp);
void comAdStateScanResults(string enemyName, double enemyHealth);
string doubleToString(double number);
string intToString(int number);
bool isRandEncounter();
void randomEncounter(Player *player,Sound *sound,Narrator *narrator);
bool combatRound(Player *player, Enemy *enemy, Sound *sound, bool ran);
void playerFindsItem(string playerName,string itemName,double itemWeight,double playerWeight);
void playerFindsGold(string playerName,double coinCnt,double playerCoinCnt);
};
#endif // COMBATADMIN_H
It is then instanced in the main.cpp file like this: (Snippet of the main.cpp file)
#include <iostream> // Required for input and output
#include <Item.h> // Item header file.
#include <Weapon.h> // Header files that I have made for my classes are needed for this program
#include <sstream> // Needed for proper type conversion functions
#include <windows.h> // for PlaySound() and other functions like sleep.
#include <time.h> // Needed to seed the rand() function.
#include <mmsystem.h> // Not sure about this one, possibly defunct in this program.
#include <stdio.h> // Needed for a similar kind of output as iostream for various functions error msgs.
#include <irrKlang.h> // The header file of the sound lib I am using in this program.
#include <Narrator.h> // The narrators's header file.
#include <Pibot.h> // Other header files of classes.
#include <Armour.h>
#include <Player.h>
#include <Weapon.h>
#include <CombatAdmin.h>
using namespace irrklang;
using namespace std;
// Forward referenced functions
void seedRandom(); // Seeds the random number so it will be random as apposed to pseudo random.
string getPlayerName(string temp); // Gets the player's new name.
int main(int argc, char* argv[])
{
// Variables and object pointers declared here.
CombatAdmin *comAd = new CombatAdmin(); // Handles combat.
Narrator *narrator = new Narrator(); // The Narrator that says stuff
Pibot *piebot = new Pibot(); // PIbot, the player's trusty companion
string temp; // Temp string for input and output
However, when I try to compile the project, I get the following error:
C:\Documents and Settings\James Moran.HOME-B288D626D8\My Documents\C++ projects\Test Project\main.cpp|59|undefined reference to `CombatAdmin::CombatAdmin()'|
I am using the Code::Blocks IDE (ver 10.05), with the GNU GCC compiler. The project is of type "Console application". I am using windows XP 32 bit SP3.
I have tried changing to search directories to include where the object files are, but no success there.
As can be seen from the code, the narrator and PIbot are instanced just fine. (then used, not shown)
My question is, therefore, what do I need to do to stop these errors occurring? As when I encountered similar "Undefined reference to x" errors before using libraries. I had just forgotten to link to them in Code::Blocks and as soon as I did, they would work.
As this class is of my own making I am not quite sure about this.
Do say if you need more information regarding the code etc.
You have declared the default constructor (CombatAdmin()) and thus prevented the compiler from automatically generating it. Thus, you either need to 1) remove declaration of the default constructor from the class, or 2) provide an implementation.
I had this kind of error and the cause was that the CombatAdmin.cpp file wasn't selected as a Build target file: Prject->Properties->Build targets
Are you sure you've to include your header as:
#include <CombatAdmin.h>
?
I think you need to include your header file as:
#include "CombatAdmin.h"
And same for other headers written by you, like these:
#include "Armour.h"
#include "Player.h"
#include "Weapon.h"
//and similarly other header files written by you!
See this topic:
What is the difference between #include <filename> and #include "filename"?
My solution was just to add a line in the header before the class defenition:
class CombatAdmin;

boost split compile issue

I have the following code snippet. I am compiling using the sun studio 12 compiler and have tried boost 1.33 and 1.39
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
using namespace boost;
using namespace std;
int main(int argc, char* argv[])
{
string exbyte = "0x2430";
string exbytes = "0x2430,2430";
typedef vector< string > SplitVec;
SplitVec res1 ;
split(res1 , exbyte, is_any_of(",") );
return 0
}
I get the following compile error:
"/bb/source/boost/boost_1_39_0/boost/algorithm/string/iter_find.hpp", line 175: Error, nomatchoverin: Could not find a match for std::vector::vector(boost::transform_iterator, boost::algorithm::split_iterator, boost::use_default, boost::use_default>, boost::transform_iterator, boost::algorithm::split_iterator, boost::use_default, boost::use_default>) needed in boost::algorithm::iter_split, std::string, boost::algorithm::detail::token_finderF>>(std::vector&, std::string &, boost::algorithm::detail::token_finderF>)
If anybody has thoughts on this that would be awesome. Since I am cotemplateing strtok(only kidding)
Other than the missing semi-colon after return 0, which I assume is an unrelated typo, your code compiles fine for me, using gcc 4.3.2.
According to the documentation for boost::split, you're using the function correctly, so I don't think this is a coding error. Are you sure you have boost installed correctly?
Edit: It may be that Boost doesn't support your particular compiler, so parts of boost may not work for you. See here for a list of supported compilers, along with various issues which affect each compiler.
It sounds like your compiler's STL implementation only provides a vector ctor taking vector::iterator's and not any iterator class. You can verify this by taking a look at the vector header file.
You may able to work around this by using STLPort which apparently can be used with Sun Studio 12.