views:

949

answers:

2

I'm pretty new to programming and am generally confused by header files and includes. I would like help with an immediate compile problem and would appreciate general suggestions about cleaner, safer, slicker ways to write my code.

I'm currently repackaging a lot of code that used to be in main() into a Simulation class. I'm getting a compile error with the header file for this class. I'm compiling with gcc version 4.2.1.

 // Simulation.h
#ifndef SIMULATION_H
#define SIMULATION_H

#include <cstdlib>
#include <iostream>
#include <cmath>
#include <string>
#include <fstream>
#include <set>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/composite_key.hpp> 
#include <boost/shared_ptr.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/tuple/tuple_io.hpp>

#include "Parameters.h"
#include "Host.h"
#include "rng.h"
#include "Event.h"
#include "Rdraws.h"

typedef multi_index_container< // line 33 - first error
  boost::shared_ptr< Host >,
  indexed_by< 
    hashed_unique< const_mem_fun<Host,int,&Host::getID> >, // 0 - ID index
    ordered_non_unique< tag<age>,const_mem_fun<Host,int,&Host::getAgeInY> >, // 1 - Age index
    hashed_non_unique< tag<household>,const_mem_fun<Host,int,&Host::getHousehold> >, // 2 - Household index
    ordered_non_unique< // 3 - Eligible by age & household
      tag<aeh>,
      composite_key<
    Host,
    const_mem_fun<Host,int,&Host::getAgeInY>,
    const_mem_fun<Host,bool,&Host::isEligible>,
    const_mem_fun<Host,int,&Host::getHousehold>
    >
      >,
    ordered_non_unique< // 4 - Eligible by household (all single adults)
      tag<eh>,
      composite_key<
    Host,
    const_mem_fun<Host,bool,&Host::isEligible>,
    const_mem_fun<Host,int,&Host::getHousehold>
    >
      >,
    ordered_non_unique< // 5 - Household & age
      tag<ah>,
      composite_key<
    Host,
    const_mem_fun<Host,int,&Host::getHousehold>,
    const_mem_fun<Host,int,&Host::getAgeInY>
    >
       >
    > // end indexed_by
  > HostContainer; 

typedef std::set<int> HHSet;

class Simulation
{
  public:
  Simulation( int sid );
  ~Simulation();

  // MEMBER FUNCTION PROTOTYPES
  void runDemSim( void );
  void runEpidSim( void );
  void ageHost( int id );
  int calcPartnerAge( int a );
  void executeEvent( Event & te );
  void killHost( int id );
  void pairHost( int id );
  void partner2Hosts( int id1, int id2 );
  void fledgeHost( int id );
  void birthHost( int id );
  void calcSI( void );
  double beta_ij_h( int ai, int aj, int s );
  double beta_ij_nh( int ai, int aj, int s );

 private:
  // SIMULATION OBJECTS
  double t;
  double outputStrobe;
  int idCtr;
  int hholdCtr;
  int simID;
  RNG rgen;
  HostContainer allHosts; // shared_ptr to Hosts - line 102 - second error
  HHSet allHouseholds; 
  int numInfecteds[ INIT_NUM_AGE_CATS ][ INIT_NUM_STYPES ]; 
  EventPQ currentEvents; 

  // STREAM MANAGEMENT
  void writeOutput();
  void initOutput();
  void closeOutput();

  std::ofstream ageDistStream;
  std::ofstream ageDistTStream;
  std::ofstream hhDistStream;
  std::ofstream hhDistTStream;

  std::string ageDistFile;
  std::string ageDistTFile;
  std::string hhDistFile; 
  std::string hhDistTFile;
};

#endif

I'm hoping the other files aren't so relevant to this problem. When I compile with

g++ -g -o -c a.out -I /Applications/boost_1_42_0/ Host.cpp Simulation.cpp rng.cpp main.cpp Rdraws.cpp 

I get

Simulation.h:33: error: expected initializer before '<' token
Simulation.h:102: error: 'HostContainer' does not name a type

and then a bunch of other errors related to not recognizing the HostContainer.

It seems like I have all the right Boost #includes for the HostContainer to be understood. What else could be going wrong?

I would appreciate immediate suggestions, troubleshooting tips, and other advice about my code. My plan is to create a "HostContainer.h" file that includes the typedef and structs that define its tags, similar to what I'm doing in "Event.h" for the EventPQ container. I'm assuming this is legal and good form.

+2  A: 

The multi_index_container seems to be in namespace boost. So you have to refer to it either explicitly with boost::multi_index_container, or use using declarations/directives.

The HostContainer error is caused by the first error. Usually you should address C++ compilation errors in order.

mkj
Gaaaaaaaaaaaaaaaahhhhhhh. Right, thank you. I'm now getting problems with container elements "indexed_by", "hashed_unique", and "const_mem_fun". Solution for those issues is at http://lists.boost.org/Archives/boost/2008/09/142085.php
Sarah
+1  A: 

To expand on my comment, here's how you could break this up to make it (a) readable, (b) maintainable, and (c) easier to debug. Basically, you create typedefs for each of the index types, then use those in your container definition:

using namespace boost;
using namespace boost::multi_index;

typedef hashed_unique< 
            const_mem_fun<Host,int,&Host::getID> 
        > IDIndex;

typedef ordered_non_unique< 
            tag<age>,
            const_mem_fun<Host,int,&Host::getAgeInY> 
        > AgeIndex;

typedef hashed_non_unique< 
            tag<household>,
            const_mem_fun<Host,int,&Host::getHousehold> 
        > HouseholdIndex;

typedef ordered_non_unique<
            tag<aeh>,
            composite_key<
                Host,
                const_mem_fun<Host,int,&Host::getAgeInY>,
                const_mem_fun<Host,bool,&Host::isEligible>,
                const_mem_fun<Host,int,&Host::getHousehold>
            >
        > EligibilityByAgeAndHouseholdIndex;

typedef ordered_non_unique<
            tag<eh>,
            composite_key<
                Host,
                const_mem_fun<Host,bool,&Host::isEligible>,
                const_mem_fun<Host,int,&Host::getHousehold>
            >
        > EligibilityByHouseholdIndex;

typedef ordered_non_unique<
            tag<ah>,
            composite_key<
                Host,
                const_mem_fun<Host,int,&Host::getHousehold>,
                const_mem_fun<Host,int,&Host::getAgeInY>
            >
        > HouseholdAndAgeIndex;

typedef multi_index_container<
    boost::shared_ptr<Host>,
    indexed_by< 
        IDIndex,
        AgeIndex,
        HouseholdIndex,
        EligibilityByAgeAndHouseholdIndex,
        EligibilityByHouseholdIndex,
        HouseholdAndAgeIndex
    >
> HostContainer; 

It is self-documenting because the index names are typedefed, so you don't need the comments to describe the purpose of the indices. Since the container definition is quite short, you can omit the "end indexed_by" type comments as well.

I don't recommend actually using the using directive; I just put it there so it would compile without me changing your code too much.

James McNellis
Thanks very much, James. That makes sense. Is there a problem with the "using" directive if I have all this in a header file strictly for defining the HostContainer? Makes things a lot simpler to read.
Sarah
@Sarah: You shouldn't use the using directive, especially not in the header. I'd just bite the bullet and spell out the names.
James McNellis