When I try to compile my code, I get this error:

------ Build started: Project: SUD, Configuration: Debug Win32 ------
Compiling...
baseent.cpp
c:\program files\microsoft visual studio 9.0\vc\include\xmemory(52) : error C2558: class 'BaseEnt' : no copy constructor available or copy constructor is declared 'explicit'
        c:\program files\microsoft visual studio 9.0\vc\include\xmemory(155) : see reference to function template instantiation 'void std::_Construct<BaseEnt,_Ty>(_T1 *,const _T2 &)' being compiled
        with
        [
            _Ty=BaseEnt,
            _T1=BaseEnt,
            _T2=BaseEnt
        ]
        c:\program files\microsoft visual studio 9.0\vc\include\xmemory(154) : while compiling class template member function 'void std::allocator<_Ty>::construct(BaseEnt *,const _Ty &)'
        with
        [
            _Ty=BaseEnt
        ]
        c:\program files\microsoft visual studio 9.0\vc\include\vector(429) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
        with
        [
            _Ty=BaseEnt
        ]
        c:\program files\microsoft visual studio 9.0\vc\include\vector(439) : see reference to class template instantiation 'std::_Vector_val<_Ty,_Alloc>' being compiled
        with
        [
            _Ty=BaseEnt,
            _Alloc=std::allocator<BaseEnt>
        ]
        c:\documents and settings\tom\my documents\visual studio 2008\projects\sud\sud\baseent.h(25) : see reference to class template instantiation 'std::vector<_Ty>' being compiled
        with
        [
            _Ty=BaseEnt
        ]
Generating Code...
Compiling...
main.cpp
Generating Code...
Build log was saved at "file://c:\Documents and Settings\tom\My Documents\Visual Studio 2008\Projects\SUD\SUD\Debug\BuildLog.htm"
SUD - 1 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

I clicked on it, and it pointed me to this line of code: extern std::vector<BaseEnt> entities; This is where BaseEnt is defined:

class BaseEnt{
	int id;
	static int count;
	std::string hashcode;
	std::string name;
public:
	BaseEnt();
	BaseEnt(std::string name);
	BaseEnt(BaseEnt &other);
	~BaseEnt();

	int GetID();
	std::string GetHashCode();
	std::string GetClassName();
    int GetCount();
};

This is where it's member definitions are:

int BaseEnt::count = 1;

std::vector<BaseEnt> entities(;

BaseEnt::BaseEnt()
:id(count), name("unassigned"), hashcode(HashCode())
{
	name += HashCode();
	entities[id] = *this;
	count++;
}

BaseEnt::BaseEnt(std::string classname)
:id(count), name(classname), hashcode(HashCode())
{
	entities[id] = *this;
	count++;
}

BaseEnt::BaseEnt(BaseEnt &other)
:id(other.GetID()), name(other.GetClassName()), hashcode(other.GetHashCode())
{
	entities[id] = *this;
	count++;
}

BaseEnt::~BaseEnt()
{
	count--;
}

std::string BaseEnt::GetClassName()
{ return name; }
int BaseEnt::GetCount()
{ return BaseEnt::count; }
std::string BaseEnt::GetHashCode()
{ return hashcode; }
int BaseEnt::GetID()
{ return id; }

I have never seen this error, and I can't figure out what it means, because I've got a copy constructor in my class(line 9).

And help will be appreciated.

Edited 7 Years Ago by tomtetlaw: n/a

Hey Tom.
Looking at the error messages and the fact that some of them are referring to a vector and then looking at line 3 of your final block of code:

std::vector<BaseEnt> entities(;

Note: You haven't closed the brackets ')' !!

I'm beginning to wonder if the compiler is getting a bit confused and is thinking that the code after the opening bracket are arguments to the constructor for the vector of BaseEnt's...Perhaps throwing the errors you're seeing....

What happens after you close the brackets and then try to recompile??

std::vector<BaseEnt> entities();

Give that a shot and see what happens!

Cheers for now,
Jas.

That was just an error by me when copying and pasting it.
This is what it looks now: std::vector<BaseEnt> entities(MAX_ENTITIES); MAX_ENTITIES is a macro with the value of 100000.

Any help will and has been appreciated : )

OK, so looking at your original post again, you said that clicking on the error brought you to this line of code: extern std::vector<BaseEnt> entities; This code looks like it's from another file which you haven't posted any other code for (apart from the above line).

Looking at the errors I'm thinking that where your extern is declared, perhaps the compiler is trying to copy the original 'entities' variable and the STL code is for some reason having difficulty finding an appropriate copy constructor for the vector of BaseEnts...

So looking at the line of code that produces the error, you've got 'entities' declared as an extern, meaning that the variable is declared externally (obvioulsy in BaseEnt.cpp).

Now looking at the declaration of 'entities' in BaseEnt.cpp, one thing immediately strikes me...If you are using this variable externally in other .cpp files/classes, shouldn't it be static? I wonder if that might be causing the errors you're seeing. As 'entities' is not static in BaseEnt.cpp, who's to say that its even in scope when the extern is declared in your other .cpp file? Perhaps this is causing the STL code to trip up!

So making 'entities' static in BaseEnt.cpp might be worth a trying for starters.

I'd also consider perhaps making it static and putting it into an unnamed namespace in BaseEnt.cpp (making it private to the BaseEnt module) and then creating a static accessor function in BaseEnt which can return a pointer or reference to 'entities' (BaseEnt::GetEntities()?).

That way you won't have to declare 'entities' as an external variable in your other classes/files which need to use it, you'd just use the BaseEnt::GetEntities() function to get a pointer or reference to the entities variable instead. It would make your code more readable, and when debugging you'd also easily be able to track which parts of your code were using/modifying 'entities' by doing a search for instances of BaseEnt::GetEntities().

Depending on how you're going to be using entities in your other classes, you might also want to consider creating a version that will return a const pointer or const reference too!

Other than that, I'm not sure what to suggest. It definitely appears to be some kind of STL related error. I've not seen these errors before either, so I'm not entirely sure what is causing the problem.

Anyway, that's me pretty much out of ideas!
Cheers for now,
Jas.
[EDIT]
p.s. If you have any further problems, perhaps .zip up and post your entire project and I'm sure someone can do some digging!

Edited 7 Years Ago by JasonHippy: n/a

I haven't got VS2008, so I can't load the original project. However, I've bunged the files into a VS2003 project and attempted to compile.

I can see the errors you're getting and I've noticed that if I comment out the copy constructor, those wierd errors are not thrown. So there is something about your copy constructor that the compiler doesn't like.

Offhand I'm still not sure exactly what the problem is though!

Obviously, because you've got that static counter that gets altered every time a new BaseEnt is created or destroyed, you need a custom copy constructor...So sticking with the default copy constructor is out of the question.

hmmm....More digging is in order...

BTW: Alongside commenting out the copy constructor, I've made the following edits to baseent.h:

#pragma once

#include <vector>
#include <string>

#define MAX_ENTITIES 500

class BaseEnt{
	int id;
	std::string hashcode;
	std::string name;
public:
	BaseEnt();
	BaseEnt(std::string name);
	//BaseEnt(BaseEnt &other);
	~BaseEnt();

	int GetID();
	int GetCount();
	std::string GetHashCode();
	std::string GetName();
};

namespace // contents are local/private to this module
{
	// The statics only need to be declared here in the header.
	static std::vector<BaseEnt> entities(MAX_ENTITIES);
	static int count=0;
}
// allow modules outside of baseent.cpp to be able to access the list of entities...
static std::vector<BaseEnt>& GetEntities(){return entities;}

BaseEnt FindClass_FromName  (std::string classname);
BaseEnt FindClass_FromHash  (std::string classhash);
BaseEnt FindClass_FromID    (int classid);
BaseEnt FindClass_FromCount (int classcount);

and baseent.cpp:

#include <iostream>
#include <string>
#include <vector>
#include "baseent.h"
#include "common_func.h"


BaseEnt::BaseEnt()
:id(count), name("unassigned"), hashcode(HashCode())
{
	name += hashcode;
	entities[id] = *this;
	count++;
}

BaseEnt::BaseEnt(std::string classname)
:id(count), name(classname), hashcode(HashCode())
{
	entities[id] = *this;
	count++;
}

/*BaseEnt::BaseEnt(BaseEnt &other)
:id(other.GetID()), name(other.GetName()), hashcode(other.GetHashCode())
{
	entities[id] = *this;
	count++;
}*/

BaseEnt::~BaseEnt()
{
	count--;
}

std::string BaseEnt::GetName()
{ return name; }
int BaseEnt::GetCount()
{ return count; }
std::string BaseEnt::GetHashCode()
{ return hashcode; }
int BaseEnt::GetID()
{ return id; }



BaseEnt FindClass_FromCount(int classcount)
{
	for(int i = 0; i < MAX_ENTITIES; ++i)
		if(entities[i].GetCount() == classcount)
			return entities[i];
	return 0;
}

BaseEnt FindClass_FromHash(std::string classhash)
{
	for(int i = 0; i < MAX_ENTITIES; ++i)
		if(entities[i].GetHashCode() == classhash)
			return entities[i];

	return 0;
}

BaseEnt FindClass_FromID(int classid)
{
	for(int i = 0; i < MAX_ENTITIES; ++i)
		if(entities[i].GetID() == classid)
			return entities[i];

	return 0;
}

BaseEnt FindClass_FromName(std::string classname)
{
	for(int i = 0; i < MAX_ENTITIES; ++i)
		if(entities[i].GetName() == classname)
			return entities[i];

	return 0;
}

Cheers for now,
Jas.

Ah...Of course!

The parameter to your copy constructor should be const..
e.g.

BaseEnt(const BaseEnt &other);

Also you need to alter the signatures of GetName, GetHashCode and GetID so they are const.

So your baseent.h needs to look like this:

#pragma once

#include <vector>
#include <string>

#define MAX_ENTITIES 500

class BaseEnt{
	int id;
	std::string hashcode;
	std::string name;
public:
	BaseEnt();
	BaseEnt(std::string name);
	BaseEnt(const BaseEnt& other);
	~BaseEnt();

	int GetID() const;
	static int GetCount();
	std::string GetHashCode() const;
	std::string GetName() const;
};

namespace
{
	// The statics only need to be declared here in the header.
	static std::vector<BaseEnt> entities(MAX_ENTITIES);
	static int count=0;
}
// allow modules outside of baseent.cpp to be able to access the list of entities...
static std::vector<BaseEnt>& GetEntities(){return entities;}

BaseEnt FindClass_FromName  (std::string classname);
BaseEnt FindClass_FromHash  (std::string classhash);
BaseEnt FindClass_FromID    (int classid);
BaseEnt FindClass_FromCount (int classcount);

And baseent.cpp like so:

#include <iostream>
#include <string>
#include <vector>
#include "baseent.h"
#include "common_func.h"


BaseEnt::BaseEnt()
:id(count), name("unassigned"), hashcode(HashCode())
{
	name += hashcode;
	entities[id] = *this;
	count++;
}

BaseEnt::BaseEnt(std::string classname)
:id(count), name(classname), hashcode(HashCode())
{
	entities[id] = *this;
	count++;
}

BaseEnt::BaseEnt(const BaseEnt& other)
:id(other.GetID()), name(other.GetName()), hashcode(other.GetHashCode())
{
	entities[id] = *this;
	count++;
}

BaseEnt::~BaseEnt()
{
	count--;
}

std::string BaseEnt::GetName() const
{ return name; }
int BaseEnt::GetCount()
{ return count; }
std::string BaseEnt::GetHashCode() const
{ return hashcode; }
int BaseEnt::GetID() const
{ return id; }



BaseEnt FindClass_FromCount(int classcount)
{
	for(int i = 0; i < MAX_ENTITIES; ++i)
		if(entities[i].GetCount() == classcount)
			return entities[i];
	return 0;
}

BaseEnt FindClass_FromHash(std::string classhash)
{
	for(int i = 0; i < MAX_ENTITIES; ++i)
		if(entities[i].GetHashCode() == classhash)
			return entities[i];

	return 0;
}

BaseEnt FindClass_FromID(int classid)
{
	for(int i = 0; i < MAX_ENTITIES; ++i)
		if(entities[i].GetID() == classid)
			return entities[i];

	return 0;
}

BaseEnt FindClass_FromName(std::string classname)
{
	for(int i = 0; i < MAX_ENTITIES; ++i)
		if(entities[i].GetName() == classname)
			return entities[i];

	return 0;
}

That should get rid of all of those rather nasty errors!

Cheers for now,
Jas.

Hey man thanks for your posts, they have helped me alot to reach the next stage of my project. Just if you're wondering, I am making a Text-based SUD(Single User Dungeon). Thanks again mate.

This article has been dead for over six months. Start a new discussion instead.