field ‘value’ has incomplete type - c++

I have a C++ interdependence problem and i can not understand where the problem is...
Here are my headers:
json.array.h
#ifndef __JSON_ARRAY__
#define __JSON_ARRAY__
#include "json.object.h"
class JSON_OBJECT;
/* JSON_ARRAY */
class JSON_ARRAY {
int size;
custom_list<JSON_OBJECT> * container;
...
};
#endif
json.object.h
#ifndef __JSON_OBJECT__
#define __JSON_OBJECT__
#include "hash.h"
#include "elem_info.h"
#include "json.type.h"
class JSON_TYPE;
class elem_info;
/* JSON_OBJECT */
class JSON_OBJECT {
custom_list<elem_info> *H;
int HMAX;
unsigned int (*hash) (std::string);
...
};
#endif
json.type.h
#ifndef __JSON_TYPE__
#define __JSON_TYPE__
#include "json.object.h"
#include "json.array.h"
class JSON_OBJECT;
class JSON_ARRAY;
class JSON_TYPE {
JSON_ARRAY * _JSON_ARRAY_;
JSON_OBJECT * _JSON_OBJECT_;
std::string _JSON_OTHER_;
std::string _JSON_TYPE_;
...
};
#endif
elem_info.h
#ifndef __ELEM_INFO__
#define __ELEM_INFO__
#include "json.type.h"
class JSON_TYPE;
class elem_info {
public:
std::string key;
JSON_TYPE value;
...
};
#endif
main.cpp
#include <iostream>
#include <string>
#include "custom_list.h" // it inculdes cpp also
#include "json.type.h"
#include "elem_info.h"
#include "json.object.h"
#include "json.array.h"
#include "json.type.cpp"
#include "elem_info.cpp"
#include "json.object.cpp"
#include "json.array.cpp"
int main()
{
JSON_ARRAY * root = new JSON_ARRAY;
JSON_OBJECT obj;
JSON_OBJECT obj1;
JSON_OBJECT * obj2 = new JSON_OBJECT;
JSON_TYPE * type = new JSON_TYPE;
...
}
When i try to compile my code, i have this error:
elem_info.h:10:15: error: field ‘value’ has incomplete type
JSON_TYPE value;
It looks like it cant find JSON_TYPE. I cant understand where is the problem.

You have a forward declaration here
class JSON_TYPE;
class elem_info {
public:
std::string key;
JSON_TYPE value;
...
};
But value is an instance of JSON_TYPE. You can only forward declare if you have members that are pointers or references, not actual instances.
In fact, since you have a full include before that forward declaration, you don't need the forward declaration at all, and as I said it wouldn't help you anyway. You'd be fine with:
#ifndef __ELEM_INFO__
#define __ELEM_INFO__
#include "json.type.h"
class elem_info {
public:
std::string key;
JSON_TYPE value;
...
};
#endif

You can't do:
class JSON_TYPE;
class elem_info {
public:
std::string key;
JSON_TYPE value;
...
};
JSON_TYPE is an incomplete type. You can have a pointer or reference but no actual instance since the compiler does not know what it is.

json.type.h includes json.array.h which includes json.object.h which includes json.type.h.
That can't work.

Related

STD error: wrong number of template arguments (1, should be 3)

I have three class. One is abstract, second is based on the abstract one and its storing pointers in std::vector to instances of another.
I want to create std::shared_ptr of ClientRepository to pass it to the Manager class instance in the future.
There is a template class called "Repository". I want to use it to create a few types of Repositories, for example: CarsRepository, ItemsRepository, etc.
Unfortunately I am getting an error while compiling:
main.cpp:84:139: error: template argument 1 is invalid
std::shared_ptr, std::vector> > p = std::make_shared;
^
Repository.hpp
#ifndef REPOSITORY_HPP
#define REPOSITORY_HPP
#include <string>
template<typename typeBOOL, typename typeShared_ptr, typename VectorOfSmarPtrs > class Repository
{
protected:
VectorOfSmarPtrs nameOfVector;
public:
virtual typeBOOL create(const typeShared_ptr&) = 0;
};
#endif
ClientRepository.hpp
#ifndef CLIENTREPOSITORY_HPP
#define CLIENTREPOSITORY_HPP
#include <memory>
#include <string>
#include "Client.hpp"
#include "Repository.hpp"
class ClientRepository : public Repository<bool, std::shared_ptr<Client>, std::vector<std::shared_ptr<Client> > >{
public:
bool create(const std::shared_ptr<Client> & newClient) override;
};
#endif
ClientRepository.cpp
include "ClientRepository.hpp"
bool ClientRepository::create(const std::shared_ptr<Client> & newClient) {
if(newClient != NULL){
for(int i = 0; i < this->nameOfVector.size(); i++) {
if(this->nameOfVector.at(i)->GetPersonalID() == newClient->GetPersonalID()) {
return 0;
}
}
this->nameOfVector.push_back(newClient);
return 1;
}
else return 0;
}
main.cpp
#include <iostream>
#include <memory>
#include "Client.hpp"
#include "ClientRepository.hpp"
#include "Repository.hpp"
int main(){
ClientRepository x;
std::shared_ptr<Repository< bool, std::shared_ptr<Client>, std::vector<std::shared_ptr<Client>> > p = std::make_shared<ClientRepository>;
}
What is wrong with this code? What should I change?
You miss parenthesis:
std::shared_ptr<Repository<bool,
std::shared_ptr<Client>,
std::vector<std::shared_ptr<Client>>>> p
// ^
= std::make_shared<ClientRepository>();
// ^^

Explicit instantion of boost multi_index container

First I would like to show the working code and then explain, how i want to change things. This is simple boost multi_index example:
//main.cpp
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include <string>
struct employee
{
int id;
std::string name;
employee(int id, const std::string& name) :id(id), name(name){}
bool operator<(const employee& e)const{ return id<e.id; }
};
typedef boost::multi_index::multi_index_container<
employee,
boost::multi_index:: indexed_by<
// sort by employee::operator<
boost::multi_index:: ordered_unique< boost::multi_index:: identity<employee> >,
// sort by less<string> on name
boost::multi_index::ordered_non_unique<boost::multi_index::member<employee, std::string, &employee::name> >
>
> employee_set;
int main()
{
employee_set es;
es.insert(employee(0, "Bob"));
}
Imagine if main.cpp is another module, without boost dependency. I want to udnerstand how to:
include some header file with boost multiindex container class being forward declared into main.cpp
define multiindex container of employees in additional .cpp file
I have tried tons of variants, but none if this works. Is it possible to create something like this?
//notmain.cpp
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/member.hpp>
#include "notmain.h"
typedef boost::multi_index::multi_index_container<
employee,
boost::multi_index::indexed_by<
// sort by employee::operator<
boost::multi_index::ordered_unique< boost::multi_index::identity<employee> >,
// sort by less<string> on name
boost::multi_index::ordered_non_unique<boost::multi_index::member<employee, std::string, &employee::name> >
>
> employee_set;
Now comes h.file I need to fill with forward declaration (or explicit initiation) of container. I may be misunderstanding these terms, but I am new to c++ and boost.
//notmain.h
#include <string>
/*
Some how here I need forward declaration or explicit initiation of boost container
class employee_set ???
*/
struct employee
{
int id;
std::string name;
employee(int id, const std::string& name) :id(id), name(name){}
bool operator<(const employee& e)const{ return id<e.id; }
};
This is final goal. I want to remind that main.cpp is imagined to be .cpp of another module, without boost dependency.
//main.cpp
#include "notmain.h"
int main()
{
employee_set es;
es.insert(employee(0, "Bob"));
}
If the type is part of a class' visible interface then any headers that class is dependent on have to be included, no way around that. If you really don't want it to be part of the visible interface consider using the pImpl idiom:
Public header
#if !defined(MYCLASS_PUBLIC_H_)
#define MYCLASS_PUBLIC_H_
struct MyClassImpl;
class MyClass {
MyClassImpl * pImpl;
public:
void SomeOperation();
};
#endif
Implementation header:
#if !defined(MYCLASS_IMPL_H_)
#define MYCLASS_IMPL_H_
#include <private_type.h>
#include "MyClass.h"
struct MyClassImpl
{
void Operation();
private:
SomePrivateType member;
};
#endif
Implementation file:
#include "MyClassImpl.h"
void MyClass::SomeOperation()
{
pImpl->Operation();
}
void MyClassImpl::Operation()
{
// do something with 'member'
}
Code that only sees the public interface:
#include "MyClass.h"
void foo()
{
MyClass inst;
inst.SomeOperation();
}

Undefined reference when using template [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 7 years ago.
I have a templated class named DataHandler
#ifndef DATAHANDLER_H
#define DATAHANDLER_H
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <set>
#include "constants.h"
template <typename T>
using Car = std::pair< T, T>;
template <typename T>
using SparseMatrix = std::vector< Car<T> >;
template <class T>
class DataHandler
{
public:
// initializes a new DataHandler only if none has been created,
// otherwise return the living instance
static DataHandler<T>* getInstance()
{
if(!dataHandler)
dataHandler = new DataHandler();
return dataHandler;
}
void readFile();
SparseMatrix<T>* getSparseBlue(){ return &sparseBlue; }
SparseMatrix<T>* getSparseRed(){ return &sparseRed; }
virtual ~DataHandler();
private:
// static DataHandler to ensure only one instance can be created
static DataHandler<T> *dataHandler;
// private constructor to use DataHandler as a Singleton
DataHandler();
int numElem = 0;
int m_rows, m_cols = -1;
#endif // DATAHANDLER_H
The source file is:
#include "data_handler.h"
#include <fstream>
#include <algorithm>
#include <omp.h>
#include <chrono>
using namespace std;
using namespace constants;
// Global static pointer used to ensure a single instance of the class.
template<typename T>
DataHandler<T>* DataHandler<T>::dataHandler = NULL;
template<typename T>
DataHandler<T>::DataHandler()
{
//ctor
}
template<typename T>
DataHandler<T>::~DataHandler()
{
//dtor
}
template<typename T>
void DataHandler<T>::readFile()
{
// do some stuff
}
// Instantiation of relevant templates
template class DataHandler<unsigned char>;
template class DataHandler<unsigned short int>;
In the last two lines I instantiate the templates which I define in main.cpp:
#include <iostream>
#include <chrono>
#include <fstream>
#include <algorithm>
#include "data_handler.h"
#include "dense_traffic_handler.h"
#include "sparse_traffic_handler.h"
#include "constants.h"
using namespace std;
// Check the number of rows/cols to choose between char or short int for the sparse case
bool matrixIsSmall()
{
return true;
}
void integerCase()
{
typedef unsigned char T;
DataHandler<T> *dh = DataHandler<T>::getInstance();
dh->readFile();
DenseTrafficHandler dth(dh); // ****** ERROR HERE *****
}
void charCase()
{
typedef unsigned char T;
DataHandler<T> *dh = DataHandler<T>::getInstance();
dh->readFile();
DenseTrafficHandler dth(dh); // ****** ERROR HERE *****
SparseTrafficHandler<T> sth;
set<unsigned short int> step = dh->getstep();
int currentStep = 0;
set<unsigned short int>::const_iterator stepToSave = step.begin();
}
int main(int argc, char *argv[])
{
if(matrixIsSmall())
charCase();
else
integerCase();
return 0;
}
Compiler gives me an error: undefined reference to DenseTrafficHandler::DenseTrafficHandler<unsigned short>(DataHandler<unsigned short>*)
DenseTrafficHandler header is like that:
#ifndef TRAFFICHANDLER_H
#define TRAFFICHANDLER_H
#include "constants.h"
#include "data_handler.h"
class DenseTrafficHandler
{
public:
template<typename T>
DenseTrafficHandler(DataHandler<T> *dh);
virtual ~DenseTrafficHandler();
private:
int m_cols, m_rows;
char* data;
char ** dense = NULL;
};
#endif // TRAFFICHANDLER_H
DenseTrafficHandler source is:
#include "dense_traffic_handler.h"
using namespace std;
using namespace constants;
template <typename T>
DenseTrafficHandler::DenseTrafficHandler(DataHandler<T> *datah)
{
DataHandler<T> *dh = datah;
dense = dh->getDense();
m_rows = dh->getm_rows();
m_cols = dh->getm_cols();
}
DenseTrafficHandler::~DenseTrafficHandler()
{
//dtor
}
So I have two questions:
Why do I receive this error and how can I manage it?
Is there a way in DataHandler source to not specify
template <typename T>
DataHandler<T>::functionName() for every function? (I mean something like using namespace Datahandler<T>)
You receive this error because compiler did not generate the code for this template type. One of solutions is to tell the compiler to do this explicitly by template instantiation:
add to your DenseTrafficHandler.cpp:
template class DenseTrafficHandler<unsigned short>;
Yes, just implement it in the header file. Reading more about it here.

Template class CArray compile under gcc, Error: the class which used as a parameter of a function undeclared

#ifndef _ALLOCATOR_H
#define _ALLOCATOR_H
#include "ace/OS_NS_stdio.h"
#include "ace/OS_NS_string.h"
#include "ace/MMAP_Memory_Pool.h"
#include "ace/Malloc_T.h"
#include "ace/Null_Mutex.h"
#include "ace/PI_Malloc.h"
#include "ace/OS_NS_unistd.h"
#include "ace/Thread_Mutex.h"
#include "ace/Process_Mutex.h"
#include <string>
using namespace std;
class CAllocator
{
public:
CAllocator();
~CAllocator(void);
public:
bool Create(char* strPoolName);
void Destroy();
public:
char* NewMem(char* strBlockName,int nBlockSize);
char* FindMem(char* strBlockName);
bool FreeMem(char* strBlockName);
private:
typedef ACE_Malloc_T <ACE_MMAP_MEMORY_POOL,
ACE_Process_Mutex,
ACE_PI_Control_Block>
ALLOCATOR;
ALLOCATOR* m_pAllocator;
};
#endif //_ALLOCATOR_H
#ifndef _ARRAY_H
#define _ARRAY_H
#include "allocator.h"
template<typename T>
class CArray
{
public:
bool CreateArray(CAllocator* pAllocator,char* strArrayName,int nArraySize);
bool OpenArray(CAllocator* pAllocator,char* strArrayName);
public:
CArray()
{
m_pArrayData = NULL;
}
~CArray()
{
m_pArrayData = NULL;
}
public:
T* GetObject(int nIndex);
int GetArraySize();
private:
T* m_pArrayData;
};
#include "array.cpp"
#endif //_ARRAY_H
In the function CreateArray of the template class CArray,
the gcc compiler says CAllocator has not been declared.
but all the code worked under vs2010
please help,thanks gurus
Please stop naming like _ALLOCATOR_H. Name start with __ or _ followed by a capital letter is reserved for using by compiler and standard.
– Danh
change #ifndef _ALLOCATOR_H #define _ALLOCATOR_H to #ifndef ALLOCATOR_H #define ALLOCATOR_H Everything is ok! Thank u all – Jack

‘Creature’ was not declared in this scope

How to fix error in Hero.h ?
GCC C++ compiler flags : -c -fmessage-length=0 -std=gnu++11 ;
I update g++ to 4.8.1
// Creature.h
#pragma once
#ifndef CREATURE_H_
#define CREATURE_H_
#include <string>
#include "Hero.h"
#include "Characteristics.h"
#include <map>
class Creature
{
private:
CreatureCharacteristics Characters;
Creature(const std::string i_name, int i_count = 0);
Creature(const Creature& Donor);
public:
typedef std::map < std::string, Creature* > Prototypes;
static Prototypes Clones_Bank;
~Creature();
const CreatureCharacteristics& Get_characteristics(){
return this->Characters;
}
static Creature*& Clone(std::string i_name, int i_count = 0);
};
#endif /* CREATURE_H_ */
// Hero.h
#pragma once
#ifndef HERO_H_
#define HERO_H_
#include "Creature.h"
#include "Characteristics.h"
#include <string>
#include <vector>
typedef std::vector<Creature*> Army; // ERROR HERE (‘Creature’ was not declared in this
scope)
class Hero {
private:
Army army;
HeroCharacteristics base_characteristics;
public:
Hero(std::string name = '\0', int attack = 0, int defense = 0):
hero_name(name)
{
base_characteristics.attack = attack;
base_characteristics.defence = defense;
};
const Army& Get_army() const
{
return army;
};
const std::string& Get_name() const
{
return hero_name;
};
const HeroCharacteristics& Get_characteristics() const
{
return base_characteristics;
};
void Add_creature(Creature* creature, int creature_count);
};
#endif /* HERO_H_ */
The problem is that Hero.h and Creature.h include each other: you have a cyclic dependency. When Hero.h includes Creature.h and Creature.h tries to include Hero.h again, HERO_H_ is already defined, and thus nothing gets inserted (if you removed the include guards, you would get an endless include cycle which is no good either).
However, it seems that Creature.h does not actually use Hero.h, so you can just remove this header. If you later do need something from the header, you may very well get away with a forward declaration. For more on this, see the C++ FAQ entry "How can I create two classes that both know about each other?".