0

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 Screenshot of Code

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.

DetlevCM
  • 149
  • 7
  • Your include guard should surround the structure definition as well. Also, this compiles and links for me. Are you linking both? – chris Jan 06 '14 at 11:43
  • Thanks, I tried that but it makes no difference, I'll amend my post. – DetlevCM Jan 06 '14 at 11:45
  • What is the exact error message you get? – Spidey Jan 06 '14 at 12:04
  • @Spidey -- Invalid Arguments' -- and -- Field 'SpeciesID' could not be resolved --, for every field (i.e. this one 4 times). – DetlevCM Jan 06 '14 at 12:11
  • I con't help but notice that you are returning a temporary variable "temp_species_loss" that you have created on the stack. You should avoid this, its C++ not Java. Your compiler shouldn't complain but try a forward declaration of the struct in main.cpp. – Oakdale Jan 06 '14 at 12:14
  • @Oakdale, NRVO generally solves that. If not NRVO, move semantics. – chris Jan 06 '14 at 12:15
  • @Oakdale Like this? #include "myheaders.h" struct SpeciesLoss; int main(int argc, char* argv[]) ... This resolved the invalid argument - this should work in my main code. (I hope). As to the temporary variable - where else do I create output in a function? (My functions tend to normally include more maths and return vectors of doubles.) – DetlevCM Jan 06 '14 at 12:17
  • @DetlevCM, I have no clue what to say to the screenshot. It's valid code. Forward-declaring the structure in `main.cpp` also adds no benefit. A few lines above it (once the #include is processed) is the full definition. – chris Jan 06 '14 at 12:17
  • @chris A colleague here is a programmer by profession and he was/is equally confused. The forward declaration also fails in my main code... where I only have the Invalid Argument error... strange. Maybe I need to try the same code on Linux - just to compare. – DetlevCM Jan 06 '14 at 12:27
  • Yes NRVO will make it work, thanks chris. I'm not a fan of depending on these optimizations though, object life-cycle management should be clear. I would prefer to create the vectors external to the functions and populate them inside through references. I suspect your problems are related to some project settings though the code looks correct. – Oakdale Jan 06 '14 at 12:35

2 Answers2

1
#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.

Miguel
  • 872
  • 1
  • 12
  • 26
  • The object is stored in a vector, though, which value-initializes new elements, and in this case, the inserted element is already value-initialized, making the next three lines redundant. The include guard issue is not an issue for this testcase, either (but it will probably bite eventually if continued to be ignored, and this is in regards to when the structure definition was repeated; it's technically fine now, though not canonical). – chris Jan 06 '14 at 11:53
  • moving my include guard to the top makes no difference at all again. It is the same problem. – DetlevCM Jan 06 '14 at 11:55
  • have you tried putting this line (std::vector< SpeciesLoss > SpeciesLossAll) insinde main? Just to try something different. – Miguel Jan 06 '14 at 11:58
  • @Miguel I have tried and just reconfirmed, I get the same error. (I need it outside though for my main code.) – DetlevCM Jan 06 '14 at 12:00
  • 1
    @DetlevCM, I really have a feeling you're only compiling and linking `main.cpp`, not both. – chris Jan 06 '14 at 12:03
  • @chris That's exactly what I'm thinking. – Miguel Jan 06 '14 at 12:07
  • @chris I'm using the build all button in Eclipse - and there are no source paths that I can set, only the header include path which is. Having said that, it is the vector< struct > that is the issue no the function which would have an error otherwise too... -> I'll update the post with a screenshot in a bit. And Visual Studio is not an option, I need Linux capability - so Eclipse and MinGW it is for me... – DetlevCM Jan 06 '14 at 12:10
  • @Miguel For the minimum working example an inline function is fine, but once you have a number of long functions it gets messy. I also found that the code will compile on Linux with GCC without an error... but I want it to be cross platform... - How would I implement my own constructor? – DetlevCM Jan 06 '14 at 12:52
1

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

DetlevCM
  • 149
  • 7