473,769 Members | 2,081 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

template class and static member variables

Hi guys

Here's the class I try to compile (see below). By itself when I have a
test.cc file for example that creates an object which is an instance of
the class SpectralProfile , it compiles fine.

1 / Now If I move the getSpectrumAtDi stance( const T &dist ) method
definition in SpectralProfofi le.cc let's say the compiler says

core/profile.cc:199: error: `kNumBins' was not declared in this scope
core/profile.cc:199: error: template argument 2 is invalid
core/profile.cc:200: error: ISO C++ forbids declaration of
`getSpectrumAtD istance' with no type
core/profile.cc:200: error: prototype for `int
wSubsurface::Sp ectralProfile<T >::getSpectrumA tDistance(const T&)' does
not match any in class `wSubsurface::S pectralProfile< T>'
core/profile.hh:229: error: candidate is: wSubsurface::Ve ctor<T,
wSubsurface::Sp ectralProfile<T >::kNumBins>
wSubsurface::Sp ectralProfile<T >::getSpectrumA tDistance(const T&)
core/profile.cc:200: error: template definition of non-template `int
wSubsurface::Sp ectralProfile<T >::getSpectrumA tDistance(const T&)'

That's my first problem... I know a bit about instanciation of
templated class in the cc file (to avoid linking errors). So would that
apply to those static const variables in that case too ?

2/

Basically kStart kEnd ... don't really have to be templated... only the
other member variables need to be.

So my question is... is there a way i can make the static variables
'untemplated' while the other are. This way when I call the function
getSpectrumAtDi stance( const T &dist ) i don't have to do:

Vector<float, SpectralProfile <float>::kNumBi nsvec =
spectralProfile->getSpectrumAtD istance( 0.1f );

which is a bit cumbersone... but maybe there's no better option ?

Thank you

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template<typena me T>
class SpectralProfile : public TProfile<T>
{
public:
static const T kStart = 400.0;
static const T kEnd = 700.0;
static const T kBinEvery = 2.0;
static const int kNumBins = static_cast<int >( ( kEnd - kStart ) /
kBinEvery + 1 );

T *m_spectrums; //!< Continuous chunk of mem that holds data

public:
SpectralProfile ( const char * spectralProfile File );
~SpectralProfil e();

Vector<T, kNumBinsgetSpec trumAtDistance( const T &dist )
{
if ( dist <= this->m_minDistanc e ) {
return Vector<T, kNumBins>( T( 0.0 ) );
}
else if ( dist this->m_maxDistanc e ) {
return Vector<T, kNumBins>( m_spectrums + ( this->m_numSamples -
1 ) * kNumBins );
}
}
};

Nov 3 '06 #1
5 3608

ma*****@yahoo.c om wrote:
Hi guys

Here's the class I try to compile (see below). By itself when I have a
test.cc file for example that creates an object which is an instance of
the class SpectralProfile , it compiles fine.
Thats a surprise. The member function getSpectrumAtDi stance(...) is not
static.
>
1 / Now If I move the getSpectrumAtDi stance( const T &dist ) method
definition in SpectralProfofi le.cc let's say the compiler says
You should keep the function inline, not in its implementation file.
Alternatively, you could specialize the template in the implementation
file.
Other options are in the faq.
http://www.parashift.com/c++-faq-lite/templates.html
read section 35-15
Any reason why you are compiling a *.cc file as opposed to a cpp?
>
core/profile.cc:199: error: `kNumBins' was not declared in this scope
core/profile.cc:199: error: template argument 2 is invalid
core/profile.cc:200: error: ISO C++ forbids declaration of
`getSpectrumAtD istance' with no type
core/profile.cc:200: error: prototype for `int
wSubsurface::Sp ectralProfile<T >::getSpectrumA tDistance(const T&)' does
not match any in class `wSubsurface::S pectralProfile< T>'
core/profile.hh:229: error: candidate is: wSubsurface::Ve ctor<T,
wSubsurface::Sp ectralProfile<T >::kNumBins>
wSubsurface::Sp ectralProfile<T >::getSpectrumA tDistance(const T&)
core/profile.cc:200: error: template definition of non-template `int
wSubsurface::Sp ectralProfile<T >::getSpectrumA tDistance(const T&)'

That's my first problem... I know a bit about instanciation of
templated class in the cc file (to avoid linking errors). So would that
apply to those static const variables in that case too ?
Say you had a class labelled MyStatics:

// mystatics.h
template<typena me T>
class MyStatics
{
static const T kStart;
static const T kEnd;
static const T kBinEvery;
static const int kNumBins;

T *m_spectrums; //!< Continuous chunk of mem that holds data
};

// mystatics.cpp
#include "mystatics. h"

template<typena me T const T MyStatics< T >::kStart = 400.0;
template<typena me T const T MyStatics< T >::kEnd = 700.0;
template<typena me T const T MyStatics< T >::kBinEvery = 2.0;
template<typena me T const int MyStatics< T >::kNumBins =
static_cast<int >( ( kEnd - kStart ) / kBinEvery + 1 );

// test.cpp
int main()
{
MyStatics<doubl eprofile;
return 0;
}

Personally, i'ld make the members non-static and simply use a MyStatics
singleton.
>
2/

Basically kStart kEnd ... don't really have to be templated... only the
other member variables need to be.
and whats preventing you from doing that too?
>
So my question is... is there a way i can make the static variables
'untemplated' while the other are. This way when I call the function
getSpectrumAtDi stance( const T &dist ) i don't have to do:

Vector<float, SpectralProfile <float>::kNumBi nsvec =
spectralProfile->getSpectrumAtD istance( 0.1f );

which is a bit cumbersone... but maybe there's no better option ?
template< typename T >
class MyStatics
{
static const double kStart;
};

or

template< typename T = double >
class MyStatics
{
static const T kStart;
};
>
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template<typena me T>
class SpectralProfile : public TProfile<T>
{
public:
static const T kStart = 400.0;
static const T kEnd = 700.0;
static const T kBinEvery = 2.0;
static const int kNumBins = static_cast<int >( ( kEnd - kStart ) /
kBinEvery + 1 );

T *m_spectrums; //!< Continuous chunk of mem that holds data

public:
SpectralProfile ( const char * spectralProfile File );
~SpectralProfil e();

Vector<T, kNumBinsgetSpec trumAtDistance( const T &dist )
Only static functions are allowed to access static variables.
Declaring a member as static is rarely a warranted solution.
{
if ( dist <= this->m_minDistanc e ) {
return Vector<T, kNumBins>( T( 0.0 ) );
}
else if ( dist this->m_maxDistanc e ) {
return Vector<T, kNumBins>( m_spectrums + ( this->m_numSamples -
1 ) * kNumBins );
}
}
};
Then there is the design of your class. Storing "chunks" of memory is
the old way of doing things. Specially when you end up transfering and
copying elements + platform padding. Why not store elements in
sequenced containers? Why aren't you using a std::vector of Ts? That
way you can have iterators, operators and streams do all the work for
you.

Nov 3 '06 #2
Thanks a lot for your answer...
1 / Now If I move the getSpectrumAtDi stance( const T &dist ) method
definition in SpectralProfofi le.cc let's say the compiler says

You should keep the function inline, not in its implementation file.
Alternatively, you could specialize the template in the implementation
file.
Other options are in the faq.
http://www.parashift.com/c++-faq-lite/templates.html
read section 35-15
okay...
Any reason why you are compiling a *.cc file as opposed to a cpp?
company's policy ;-) i don't like it much but our standard Makefile
forces the source code file to be names .hh and .cc

2/

Basically kStart kEnd ... don't really have to be templated... only the
other member variables need to be.

and whats preventing you from doing that too?

template< typename T >
class MyStatics
{
static const double kStart;
};

or

template< typename T = double >
class MyStatics
{
static const T kStart;
};
of course you are right ! I guess i need vacation...
Then there is the design of your class. Storing "chunks" of memory is
the old way of doing things. Specially when you end up transfering and
copying elements + platform padding. Why not store elements in
sequenced containers? Why aren't you using a std::vector of Ts? That
way you can have iterators, operators and streams do all the work for
you.
Ah ? Okay... I thought it was better that way... instead of having a
bunch of Vectors all other the place. I always thought in general an
application would run faster when the data it uses are located in the
same memory space. Will go back to Vectors then.

I also did that because I didn't like much the allocation of memory for
the Vectors. Since it's an array of Vectors I have to do the Vector<T,
Depth**m_spectr ums which is fine. The problem is when I need to
access the data of the Vectors. I have to do things like m_spectrum[ 10
]->w[ 12 ] (where w is the member variable of the Vector class that
hold the vector data). Or (*m_spectrum[10])[12] which is not very
elegant (as the Vector class has a [] operator that returns the value
in the w array at a certain index).

Anyway... thanks again

Nov 3 '06 #3
Peter

While I am at it ?

Is there a reason why you ask about hh/cc vs hpp/cpp ? Do you have a
preference ?

Okay I ended up coding the class that (kNumBins) becomes basically
Depth in the class. Although I am forced at the end of the .cc file to
instance the class

template class SuperProfile<fl oat, 3>;
template class SuperProfile<fl oat, 151>;
template class SuperProfile<do uble, 3>;
template class SuperProfile<do uble, 151>;

I guess the float/double thing is not a problem but I am more annoyed
by the fact that I am limited in the size of the vector (3/151) at
compile time. Does it mean I have no way if I use this approach to
create on the fly a SuperProfile instance of size lets say 200 ?

template<int Depthclass SuperProfile<do uble, Depth>;

// then later in the code

SuperProfile<do uble, 200aProfileVect orSize200; // That won't compile

In function `main':test.cc: (.text+0x24e): undefined reference to
`wSubsurface::S uperProfile<flo at, 200>::SuperProf ile(char const*, int)'

Any idea how to bypass that problem ?

////////////////////////////////////////////////////////////////////////////////////////////

//
//! \brief Profile class
//

#ifndef _PROFILE_HH_
#define _PROFILE_HH_

#include "vector.hh"
#include "exception. hh"
#include "utils.hh"

// temp
//#include "ciexyz31.h h"

namespace wSubsurface {

template<typena me T, int Depth>
class SuperProfile
{
public:
T *m_distances;
Vector<T, Depth*m_spectru ms;
int m_numSamples;
T m_minDistance;
T m_maxDistance;
public:
SuperProfile( const char *profileFile, int numSamples );
int binarySearch( const T &distance );
Vector<T, DepthgetSpectru mAtDistance( const T &dist );
};

} // end namespace

#endif // _PROFILE_HH_

//
//!\ brief Profile class, methods definitions
//

#include "profile.hh "
#include "exception. hh"

namespace wSubsurface {

template<typena me T, int Depth>
SuperProfile<T, Depth>::SuperPr ofile( const char *profileFile,
int numSamples ) :
m_distances( NULL ),
m_spectrums( NULL ),
m_numSamples( numSamples ),
m_minDistance( T( 1.0e+6 ) ),
m_maxDistance( T( 0.0 ) )
{
// Read file
ifstream ifs;

try {
ifs.open( profileFile );
if ( ifs.fail() ) {
throw( Exception( "File doesn't exist", __FILE__, __LINE__ ) );
}
}
catch( const Exception &e ) {
cerr << e.what() << endl;
ifs.close();
}

int tmp; // remove that later
ifs.read( reinterpret_cas t<char*>( &tmp ), sizeof( int ) );
ifs.read( reinterpret_cas t<char*>( &tmp ), sizeof( int ) );
ifs.read( reinterpret_cas t<char*>( &tmp ), sizeof( int ) );
ifs.read( reinterpret_cas t<char*>( &tmp ), sizeof( int ) );

m_distances = new T[ m_numSamples ];
m_spectrums = new Vector<T, Depth>[ m_numSamples ];

for ( int i = 0; i < m_numSamples; ++i ) {
ifs.read( reinterpret_cas t<char*>( &m_distances[ i ] ), sizeof( T )
);
ifs.read( reinterpret_cas t<char*>( &m_spectrums[ i ].w[ 0 ] ),
sizeof( T ) * Depth );

if ( this->m_distances[ i ] < m_minDistance ) {
m_minDistance = m_distances[ i ];
}
else if ( this->m_distances[ i ] this->m_maxDistanc e ) {
m_maxDistance = m_distances[ i ];
}
}

// Close file
ifs.close();
cerr << "num samples: " << m_numSamples << endl;
cerr << "min dist : " << m_minDistance << endl;
cerr << "max dist : " << m_maxDistance << endl;
}

template<typena me T, int Depth>
int SuperProfile<T, Depth>::binaryS earch( const T &distance )
//
//! \brief Returns array index of the closest distance.
//! \param distance is the distance we try to get the closest to
//! \return an index position in m_distances array to the closest
distance
//
{
// binary search
int first = 0, last = m_numSamples, middle = ( first + last ) / 2;

while( first < last ) {
if ( distance < m_distances[ middle ] ) {
last = middle - 1;
}
else if ( distance m_distances[ middle ] ) {
first = middle + 1;
}
else {
return middle;
}
middle = ( first + last ) / 2;
}

return ( m_distances[ middle ] - distance 0.0 ) ? middle - 1 :
middle;
}

template<typena me T, int Depth>
Vector<T, DepthSuperProfi le<T, Depth>::getSpec trumAtDistance( const T
&dist )
{
if ( dist <= m_minDistance ) {
return Vector<T, Depth>( T( 0.0 ) );
}
else if ( dist this->m_maxDistanc e ) {
return m_spectrums[ m_numSamples - 1 ];
}

int idx = binarySearch( dist );

T w = 0.5;

return m_spectrums[ idx ] * ( 1.0 - w ) + m_spectrums[ idx + 1 ] * w;
}

// instance
template class SuperProfile<fl oat, 3>;
template class SuperProfile<fl oat, 151>;
template class SuperProfile<do uble, 3>;
template class SuperProfile<do uble, 151>;

} // end of namespace

Nov 3 '06 #4
Hum I should have added that I used

3 for a RGB color
151 because that's the size of the data that use if use a spectral
curve instead of RGB to describe a color.

So I guess I am fine with those 2 templates but it would be nice to
have a mechanisme where I can create one of the fly which has the size
that I want for the size of the Vector in case one day i use more or
less than 151 values for the spetral curve.

cheers -

Nov 3 '06 #5

ma*****@yahoo.c om wrote:
Thanks a lot for your answer...
1 / Now If I move the getSpectrumAtDi stance( const T &dist ) method
definition in SpectralProfofi le.cc let's say the compiler says
You should keep the function inline, not in its implementation file.
Alternatively, you could specialize the template in the implementation
file.
Other options are in the faq.
http://www.parashift.com/c++-faq-lite/templates.html
read section 35-15

okay...
Any reason why you are compiling a *.cc file as opposed to a cpp?

company's policy ;-) i don't like it much but our standard Makefile
forces the source code file to be names .hh and .cc
>
2/
>
Basically kStart kEnd ... don't really have to be templated... only the
other member variables need to be.
and whats preventing you from doing that too?

template< typename T >
class MyStatics
{
static const double kStart;
};

or

template< typename T = double >
class MyStatics
{
static const T kStart;
};

of course you are right ! I guess i need vacation...
Then there is the design of your class. Storing "chunks" of memory is
the old way of doing things. Specially when you end up transfering and
copying elements + platform padding. Why not store elements in
sequenced containers? Why aren't you using a std::vector of Ts? That
way you can have iterators, operators and streams do all the work for
you.

Ah ? Okay... I thought it was better that way... instead of having a
bunch of Vectors all other the place. I always thought in general an
application would run faster when the data it uses are located in the
same memory space. Will go back to Vectors then.
A std::vector keeps its elements in contiguous memory. So, since
nothing stops you from making a vector of vectors...
>
I also did that because I didn't like much the allocation of memory for
the Vectors. Since it's an array of Vectors I have to do the Vector<T,
Depth**m_spectr ums which is fine. The problem is when I need to
access the data of the Vectors. I have to do things like m_spectrum[ 10
]->w[ 12 ] (where w is the member variable of the Vector class that
hold the vector data). Or (*m_spectrum[10])[12] which is not very
elegant (as the Vector class has a [] operator that returns the value
in the w array at a certain index).

Anyway... thanks again
A std::vector is actually an array on steroids. And you have a variety
of ways you can access the elements, including the operator[ ],
iterators as well as a panoply of powerfull algorithms. Its also a very
easy and safe container to use. Consider that it has the at(index)
accessor with out_of_range bounds check. The elements are allocated
and deallocated automatically, unless you choose to store pointers.

I'm not doing anything fancy:

#include <iostream>
#include <ostream>
#include <vector>

struct A // toy class
{
int n;
char c;
A() : n(0), c('a') { } // def ctor
A(size_t u, char c_) : n(static_cast<i nt>(u)), c(c_) { }
// overloaded operator<<
friend std::ostream&
operator<<(std: :ostream& os, const A& r_a)
{
os << "n = " << r_a.n;
os << "\tc = " << r_a.c;
return os;
}
};

int main()
{
char mychar('a');
const size_t Size(10); // const Size
std::vector< A va; // empty vector
for(size_t i = 0; i < Size; ++i)
{
va.push_back( A(i, mychar++) ); // push 0 to 10
}

for(size_t i = 0; i < Size; ++i)
{
std::cout << va[i] << std::endl; // <- operator [ ]
}
std::vector< A vanother(1000); // makes 1000 elements instantly
// no need to delete anything !
}

/*
n = 0 c = a
n = 1 c = b
n = 2 c = c
n = 3 c = d
n = 4 c = e
n = 5 c = f
n = 6 c = g
n = 7 c = h
n = 8 c = i
n = 9 c = j
*/

Whats the benefit? Once you learn how to use a std::vector...
all the other containers use nearly the same interface.
std::list, std::deque, etc

I'ld kindly suggest a book:
http://www.acceleratedcpp.com/
C++ Primer (4th Edition) Lippman, LaJoie, Moo
http://www.josuttis.com/ (C++ Standard Library)

All 3 are worth every penny and then some.

Nov 3 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
1632
by: Alibek | last post by:
Hello ! I have here template class with static members. and I put definition of the static member in the same ..h file where the class was declared. however, we are getting very stange errors, because static member occupy same place as some other non-static variables. and so application crashes. compiler somehow allocates same place for them.
4
3134
by: Graham Dumpleton | last post by:
When you have a template class with a static member variable, ie., template<typename T> class handle { public: static void* id() { return &id_; } private: static int id_; };
0
1644
by: Chris F Clark | last post by:
In our C++ project we have some internal bug reporting macros that we use to get useful information when the program does something unexpected. Essentially at the point of the error, we invoke an internal interactive debugger that knows the classes within our system and allow us to walk around the objects that exist at the time of the fault. It mostly works fairly well. That catch being that we have to hand implement some of the code...
7
12457
by: ank | last post by:
Hi, I was curious about how to define static data member of template class. Should I put the definition in a separate source file or in the same header file as its template class? And when this data will be initialized if it is used across many translation unit, assume that it has constructor and needs dynamic initialization? I have blindly searched for the answer but I still not thoroughly
10
2549
by: ma740988 | last post by:
Part of my confusion here is certainly my ignorance of templates and std::auto_ptr. Two topics, I've perused but need to really _delve_ into. In any event, consider the 'test' source. # include <iostream> # include <memory> class CallbackBase { public: virtual void operator()() const { };
3
1338
by: Serge Skorokhodov (216716244) | last post by:
Hi, I just seeking advice. Some background information first because I've run into issues that seems pretty obscure to me:( Quick search through KB yields next to nothing. Simplified samples work OK as well, the problems appear in rather bulky code:( I'm trying to implement some signal processing algorithm using
8
2840
by: Markus Henschel | last post by:
Hello, this is a test case of something I just can't explain myself: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include <list> typedef void (*registerfunc)(); class CMgr {
3
3173
by: Shahin Tavakoli | last post by:
Hi, I'd like to put a static member in a template class, but I don't know the syntax. I've tried out template<typename Type> class Stocker : private vector<Type> { public: static int NB;
3
5790
by: StephQ | last post by:
In utility.hpp I have: namespace utility { template <class T, double (T::*F)(double) const> class Display { private: static double resolution;
0
9589
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9423
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10216
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10049
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
6675
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5310
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5448
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3965
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3565
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.