I’ve been programing a template structure and after make it work I decided to use it on some other project. The template consists in two files. ListOctree.cpp and ListOctree.h.
While they compile and run just fine on their own (I can run the structure self-test).
When using them on the other project, both ListOctree.cpp/.h are on the ./Util directory but while Visual Studio seems to find the .h file (I can use the .h declarations anywhere on the project), it seems like it can’t find the .cpp source file where all the code declared on the .h is declared.
The files are part of the project. ists tree is something like this:
program.cpp <-- includes "Util/ListOctree.h"
/Util
ListOctree.cpp
ListOctree.h
All the classes and functions from ListOctree belong to the Util namespace.
The error that Visual C++ throws is:
error LNK2019: símbolo externo “public: __thiscall Util::ListOctree::ListOctree(int)” (…) sin resolver …
Aprox. in english:
error LNK2019: external symbol “public: __thiscall Util::ListOctree::ListOctree(int)” (…) not resolved …
When rebuilding the solution the Util/ListOctree.cpp is compiled an the .obj file generated yet it seems not to be able to link it together
I can also post the .h file but I find it too long to post now.
Annex: where and how i’m using the .h file
#include "Util/ListOctree.h"
//...
void main (){
//...
ListOctree<int>* a = new ListOctree<int>(8);
//...
}
Annex: Util/ListOctree.h
#ifndef __UTIL_LISTOCTREE
#define __UTIL_LISTOCTREE
//Conditional compilation flags
#undef _SELFTEST
#undef _DEBUG_LISTOCTREE
//Conditional compilation options
#ifdef _DEBUG_LISTOCTREE
#undef _DEALLOCATE_LISTS
#define _SELFTEST
#endif
#ifdef _SELFTEST
#include <iostream>
#endif
#ifdef _SELFTEST
#include<assert.h>
#endif
#ifdef _DEBUG_LISTOCTREE
#include <iostream>
#endif
/////////////////////////////////
#include <deque>
#include <list>
#include <iterator>
#include <math.h>
#include <exception>
//Remind me to never do this again. (xYz,XYz,XYZ,xYZ,xyz,Xyz,XyZ,xyZ,)
//A CAPS character means positive in the axis while a
//Lowercase character means negative
//FIXME Never used I think.
#define _xyz sons[0]
#define _xyZ sons[1]
#define _xYz sons[2]
#define _xYZ sons[3]
#define _Xyz sons[4]
#define _XyZ sons[5]
#define _XYz sons[6]
#define _XYZ sons[7]
namespace Util{
/**
* @brief The node class
*
* Each node stores up to 8 sons, a parent pointer and, if it
* is a Leaf node, a list of contents.
*/
template <typename T> class Node{
//Attributes
public:
///An array with all the sons
Node<T>* sons[8];
///A parent pointer
Node<T>* parent;
//The node contents (if any)
std::list<T>* c;
//Methods
public:
/// Deallocates itself AND all of it's sons
~Node();
/// Creates an empty node
Node();
/// Creates a node with its eight sons and a parent reference from an 9 pointer array
Node(Node<T>** nodes);
///Returns the node contents
std::list<T>* getContents(){return c;};
///Pushes an item into the node
void pushItem(T item);
///Removes an item from the node
void eraseItem(T item){c->erase(item);};
///Clears the node contents
void clearNode(){c->clear();};
};
/**
* @brief Container for @see Node classes
*
* This class allows a more convenient way of working with Octrees
*/
template <typename T> class ListOctree {
//Attributes
private:
int width;
Node<T>* root;
//Methods
public:
ListOctree(int width);
~ListOctree();
void pushItemAt(T item, int x, int y, int z);
void eraseItemAt(T item, int x, int y, int z);
void clearItemsAt(int x, int y, int z);
std::list<T>* getItems();
std::list<T>* operator() (int x, int y, int z){return(getItemsAt(x,y,z));};
std::list<T>* getItemsAt(int x, int y, int z);
private:
char nextNode(int x, int y, int z, int* cx, int* cy, int* cz, int width, Node<T>* n, bool createNew) throw(...);
void _pushItemAt(T item, int x, int y, int z, int cx, int cy, int cz, int width, Node<T>* n);
void _eraseItemAt(T item, int x, int y, int z, int cx, int cy, int cz, int width, Node<T>* n);
void _clearItemsAt(int x, int y, int z, int cx, int cy, int cz, int width, Node<T>* n);
std::list<T>* _getItemsAt(int x, int y, int z, int cx, int cy, int cz, int width, Node<T>* n);
void prune(Node<T>* n);
void addItemsToList(std::list<T>* lst, Node<T>* n);
};
/**
* @brief Exception used internally
*
* FIXME, never used, can't be used for some reason
*/
class ListOctreeException : public std::exception{
private:
std::string msg;
public:
ListOctreeException(){msg="ListOctreeException";};
ListOctreeException(std::string s){msg=s;};
const char* what(){return(msg.c_str());};
};
};//namespace
#endif
The declaration and the definition of templates should be kept in the same file (usually the .h). See the FAQ for details (it’s also technically possible to instantiate the template in a file that #includes the implementation (see this also)).
The keyword
exportthat was supposed to be used in the case where the two are separated, but few compilers implemented it, and it has now been removed in c++0x.