Jump to content

  • Log In with Google      Sign In   
  • Create Account


static const templates


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
8 replies to this topic

#1 webwraith   Members   -  Reputation: 227

Like
0Likes
Like

Posted 17 October 2010 - 02:42 AM

I have a reference counted smart pointer called coreRef<>, and wanted to have a static const member that is effectively a NULL value, so I tried the following;

template < typename T >
class coreRef
{
public:
/// Constructors and Destructors
~coreRef(){
...
}

coreRef( const coreRef< T >& ref ): ptr( ref.ptr ){
...
}

explicit coreRef( T* val = NULL ): ptr( NULL ){
...
}

/// Overloaded operators
coreRef& operator = ( const coreRef<T> ref ){
...
}

T* operator -> () const {
...
}

// This is the line that's causing me problems
static const coreRef< T > null;
...
}



I have an abstract class which acts as its own class factory, and to test it, I created a dummy class derived from it. However, when I tried

return coreRef<otherType>::null;

I keep getting undefined reference errors. What can I do to correct this?

[Edited by - webwraith on October 17, 2010 12:40:56 PM]

Sponsor:

#2 SiCrane   Moderators   -  Reputation: 9554

Like
0Likes
Like

Posted 17 October 2010 - 02:49 AM

Static template member variables, like non-template static variables need to be defined in addition to be declared. In your case, the syntax looks like:

template <typename T> coreRef<T> coreRef<T>::null;

Like most template code it should go in the same header that the rest of your template class lives in.

#3 Makaan   Members   -  Reputation: 100

Like
0Likes
Like

Posted 17 October 2010 - 02:50 AM

You need to specify to the compiler where the static variable is defined , so for a normal class you would write in the .cpp file

var_type your_normal_class::your_static_var = some value;

at this point the variable is referenced.

Ok but you have a template class , so this messes up the problem ,
just write in the .h file , right under your class definition:


template <class T> coreRef< T >::null = whatever value;


i guess that because of the definition in the .h file there might be errors later if the variable is not const also.

#4 webwraith   Members   -  Reputation: 227

Like
0Likes
Like

Posted 17 October 2010 - 06:37 AM

The problem is that I declare the variable const (which I appear to have missed out in the OP, sorry about that, I'll change it now), and GCC/G++ complains that I haven't defined the value at the declaration site. I suppose I could have a private variable, then return a coreRef< T >& const (or with the const at the start, I always get its location mixed up) to the private variable.

#5 SiCrane   Moderators   -  Reputation: 9554

Like
0Likes
Like

Posted 17 October 2010 - 07:04 AM

Post a minimal, but complete, code sample that demonstrates your problem. Deleting stuff from your class as posted so that it compiles and using the suggested syntax produces code that links with g++ 4.3.4.

#6 webwraith   Members   -  Reputation: 227

Like
0Likes
Like

Posted 17 October 2010 - 07:15 AM

Right, the coreRef template is exactly as above, now that I've changed the 'null' variable. I'll post the full code to that as well later if you want to see it, but the function declarations should be good. The problem comes with the following;

Abstract IGraphics class:

class IGraphics
{
protected:
static IGraphics* graphics;
public:
// use in the form "coreRef< IGraphics > grph = IGraphics::GetInterface< ConcreteGraphicsClass >();"
template < class T >
static coreRef< IGraphics > GetInterface(){
if( graphics == NULL ){
graphics = new T;
}
return coreRef< IGraphics >( graphics );
}

/// Note that the following GetXXX() functions will later be given arguments
virtual coreRef< IMesh > GetMesh() = 0; // retrieves a mesh from the mesh manager
virtual coreRef< ITexture > GetTexture() = 0; // retrieves a texture from the texture manager
virtual coreRef< ITerrain > GetTerrain() = 0; // retrieves a terrain from the terrain manager
};

IGraphics* IGraphics::graphics = NULL;




and the derived class that keeps throwing errors, along with my testing main():

class dummy : public IGraphics
{
public:

virtual coreRef< IMesh > GetMesh(){ return coreRef< IMesh >::null; } // retrieves a mesh from the mesh manager
virtual coreRef< ITexture > GetTexture(){ return coreRef< ITexture >::null; } // retrieves a texture from the texture manager
virtual coreRef< ITerrain > GetTerrain(){ return coreRef< ITerrain >::null; } // retrieves a terrain from the terrain manager

protected:

private:

};


int main(int argc, char **argv)
{
coreRef< IGraphics > graph = IGraphics::GetInterface< dummy >();
return 0;
}




The errors are to do with the returns in class 'dummy'. For each one I get an 'Undefined reference to coreRef< x >::null', where 'x' is the class in question.

Currently, each of the IMesh, ITexture and ITerrain classes are stubs that have no code in them.

#7 SiCrane   Moderators   -  Reputation: 9554

Like
0Likes
Like

Posted 17 October 2010 - 07:31 AM

A complete code sample contains everything necessary to compile. Someone should be able to copy and paste from what you've posted and see the error you're complaining about. In this case, since you're complaining about a linker error the code you post should compile. What you've posted does not.

#8 webwraith   Members   -  Reputation: 227

Like
0Likes
Like

Posted 17 October 2010 - 07:50 AM

Right, well here we go:

main.cpp:

#include <iostream>

#include "i_graphics.h"
#include "core_ref.h"

class dummy : public IGraphics
{
public:

virtual coreRef< IMesh > GetMesh(){ return coreRef< IMesh >::null; } // retrieves a mesh from the mesh manager
virtual coreRef< ITexture > GetTexture(){ return coreRef< ITexture >::null; } // retrieves a texture from the texture manager
virtual coreRef< ITerrain > GetTerrain(){ return coreRef< ITerrain >::null; } // retrieves a terrain from the terrain manager

protected:

private:

};


int main(int argc, char **argv)
{
coreRef< IGraphics > graph = IGraphics::GetInterface< dummy >();
return 0;
}



i_graphics.h:

#ifndef _CORE_GRAPHICS
#define _CORE_GRAPHICS

#include "i_mesh.h"
#include "i_texture.h"
#include "i_terrain.h"

#include "core_ref.h"

class IGraphics
{
protected:
static IGraphics* graphics;
public:
// use in the form "IGraphics* grph = IGraphics::GetInterface< ConcreteGraphicsClass >();"
template < class T >
static coreRef< IGraphics > GetInterface(){
if( graphics == NULL ){
graphics = new T;
}
return coreRef< IGraphics >( graphics );
}

/// Note that the following GetXXX() functions will later be given arguments
virtual coreRef< IMesh > GetMesh() = 0; // retrieves a mesh from the mesh manager
virtual coreRef< ITexture > GetTexture() = 0; // retrieves a texture from the texture manager
virtual coreRef< ITerrain > GetTerrain() = 0; // retrieves a terrain from the terrain manager
};

IGraphics* IGraphics::graphics = NULL;


#endif // _CORE_GRAPHICS



core_ref.h:

#ifndef _CORE_REF
#define _CORE_REF

template < typename T >
class coreRef
{
public:
/// Constructors and Destructors
~coreRef(){
if( ptr ){
ptr->count--;

if( ptr->count == 0 ){
// destroy the actual data
delete ptr->data;
ptr->data = NULL;

// there's no longer any need for ptr, so do housework
delete ptr;
}
// this class should not point to the reference anymore, don't want the user trying to access something they shouldn't
ptr = NULL;
}
}

coreRef( const coreRef< T >& ref ): ptr( ref.ptr ){
if( ptr != NULL && good() )
ptr->count++;
}

explicit coreRef( T* val = NULL ): ptr( NULL ){
if( val ){
ptr = new _counter;
ptr->data = val;
ptr->count++;
}
}

/// Overloaded operators
coreRef& operator = ( const coreRef<T> ref ){
if ( this != &ref ){
ptr = ref->ptr;
}
}

T* operator -> () const {
return *ptr->data;
}

static const coreRef< T > null;

/// For testing the validity of the pointer
bool good(){
return ( ptr->data != NULL ) ? true : false;
}
protected:

/// The counter struct keeps track of the numer of references
struct _counter{
size_t count;
T* data;
}* ptr;

};

#endif // _CORE_REF



i_mesh.h:

#ifndef _I_MESH
#define _I_MESH

class IMesh
{
public:
IMesh();
~IMesh();


protected:

private:

};


#endif // _I_MESH



i_texture.h:

#ifndef _I_TEXTURE
#define _I_TEXTURE

class ITexture
{
public:
ITexture();
~ITexture();


protected:

private:

};


#endif // _I_TEXTURE



i_terrain.h:

#ifndef _I_TERRAIN
#define _I_TERRAIN

class ITerrain
{
public:
ITerrain();
~ITerrain();


protected:

private:

};


#endif // _I_TERRAIN



That is everything currently included in my project, literal CnP.

#9 SiCrane   Moderators   -  Reputation: 9554

Like
0Likes
Like

Posted 17 October 2010 - 08:28 AM

Your core_ref.h header doesn't include the static member variable definition. See the very first response in this thread, but remember to add const.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS