Template class with "typename" - c++

I have a template class where I want to use objects of that class (along with the parameterized type) inside a map. So far this is the solution that I've been able to arrive at:
class IStatMsg;
template <typename T>
class ITier
{
public:
// Methods
ITier(TierType oType) : o_Type(oType){};
virtual ~ITier(){};
typename ITier<T> ParamITier; // line 60
ITier* Get(T oKey)
{
std::map<T, ParamITier*>::iterator it = map_Tiers.find(oKey); // line 64
if (it != map_Tiers.end())
return it->second;
return NULL;
}
void Set(T oKey, ITier* pTier)
{
map_Tiers.insert(pair<T, ParamITier*>(oKey, pTier)); // line 74
}
TierType GetType() { return o_Type; }
protected:
// Methods
// Attributes
std::map<T, ParamITier*> map_Tiers; // line 83
TierType o_Type;
private:
// Methods
// Attributes
};
But when I try to compile this code I get a long list of errors:
/home/gayanm/street/src/QueryServer_NEW/ITier.h:60:
error: expected nested-name-specifier
/home/gayanm/street/src/QueryServer_NEW/ITier.h:60:
error: ITier<T>' specified as
declarator-id
/home/gayanm/street/src/QueryServer_NEW/ITier.h:60:
error: perhaps you wantITier'
for a constructor
/home/gayanm/street/src/QueryServer_NEW/ITier.h:60:
error: two or more data types in
declaration of ITier<T>'
/home/gayanm/street/src/QueryServer_NEW/ITier.h:60:
error: expected;' before
"ParamITier"
/home/gayanm/street/src/QueryServer_NEW/ITier.h:83:
error: ParamITier' was not declared
in this scope
/home/gayanm/street/src/QueryServer_NEW/ITier.h:83:
error: template argument 2 is invalid
/home/gayanm/street/src/QueryServer_NEW/ITier.h:83:
error: template argument 4 is invalid
/home/gayanm/street/src/QueryServer_NEW/ITier.h:83:
error: ISO C++ forbids declaration of
map_Tiers' with no type
/home/gayanm/street/src/QueryServer_NEW/ITier.h:
In member function ITier<T>*
ITier<T>::Get(T)':
/home/gayanm/street/src/QueryServer_NEW/ITier.h:64:
error:ParamITier' undeclared (first
use this function)
/home/gayanm/street/src/QueryServer_NEW/ITier.h:64:
error: (Each undeclared identifier is
reported only once for each function
it appears in.)
/home/gayanm/street/src/QueryServer_NEW/ITier.h:64:
error: template argument 2 is invalid
/home/gayanm/street/src/QueryServer_NEW/ITier.h:64:
error: template argument 4 is invalid
/home/gayanm/street/src/QueryServer_NEW/ITier.h:64:
error: expected ;' before '::' token
/home/gayanm/street/src/QueryServer_NEW/ITier.h:66:
error:it' undeclared (first use this
function)
/home/gayanm/street/src/QueryServer_NEW/ITier.h:66:
error: request for member end' in
((ITier)this)->ITier::map_Tiers',
which is of non-class type int'
/home/gayanm/street/src/QueryServer_NEW/ITier.h:
In member functionvoid
ITier::Set(T, ITier)':
/home/gayanm/street/src/QueryServer_NEW/ITier.h:74:
error: request for member insert' in
((ITier*)this)->ITier::map_Tiers',
which is of non-class type int'
/home/gayanm/street/src/QueryServer_NEW/ITier.h:74:
error:pair' undeclared (first use
this function)
/home/gayanm/street/src/QueryServer_NEW/ITier.h:74:
error: expected primary-expression
before ',' token
/home/gayanm/street/src/QueryServer_NEW/ITier.h:74:
error: ParamITier' undeclared (first
use this function)
/home/gayanm/street/src/QueryServer_NEW/ITier.h:74:
error: expected primary-expression
before '>' token
/home/gayanm/street/src/QueryServer_NEW/ITier.h:
At global scope:
/home/gayanm/street/src/QueryServer_NEW/ITier.h:93:
error: baseITier' with
only non-default constructor in class
without a constructor
/home/gayanm/street/src/QueryServer_NEW/ITier.h:109:
error: expected class-name before '{'
token
Could you please point out how to fix these?
Thank You.

Line 60 does not access a depending name. What you use is ITier<T> of which the compiler knows it's a template given an argument. Instead of typename you want to use typedef ;)
Line 64 does access the depending name iterator which is a type-name, so you have to put typename before std::map. I put the two disambiguations, template and typename on this answer: Disambiguations of dependent names.
Line 74 would be right, if you fix the bug in Line 60, as far as i can see.
Line 83 is alright in itself as far as i can see.

Also, I would recommend that you pass const T& to the functions instead of T, since you cannot be sure (it's a template parameter!) that it'll be a "cheap" copy.

Thanks a lot litb. I was able to fix my code with the guidelines you provided.
class IStatMsg;
template <typename T>
class ITier
{
public:
// Methods
ITier(){};
ITier(TierType oType) : o_Type(oType){};
virtual ~ITier(){};
//typename ITier<T> ParamITier;
ITier<T>* Get(T oKey)
{
typename std::map<T, ITier<T>*>::iterator it = map_Tiers.find(oKey);
if (it != map_Tiers.end())
return it->second;
return NULL;
}
void Set(T oKey, ITier<T>* pTier)
{
map_Tiers.insert(std::pair<T, ITier<T>*>(oKey, pTier));
}
TierType GetType() { return o_Type; }
protected:
// Methods
// Attributes
std::map<T, ITier<T>*> map_Tiers;
TierType o_Type;
private:
// Methods
// Attributes
};

Related

Error when inheriting from templated class and calling templated function

I've got some template code that I'm modifying and I've run into an odd error that I can't work around. I was able to recreate the problem with the below simpler (but admittedly pointless) code snippet:
struct Widget
{
};
template <typename A>
class Foo
{
public:
template <int numA>
inline bool funcCall()
{
return numA > 0;
}
inline bool funcCallNoTemplate()
{
return false;
}
};
template <typename B>
class Bar : public Foo<B>
{
public:
// doesn't work
bool concrete()
{
return Foo<B>::funcCall<5>();
}
// works fine
bool other()
{
return Foo<B>::funcCallNoTemplate();
}
};
int main()
{
Bar<Widget> b;
b.concrete();
b.other();
return 0;
}
The error I get with GCC 4.7 is the following (line 30 is the body of Bar::concrete):
example.cxx: In member function ‘bool Bar<B>::concrete()’:
example.cxx:30: error: expected primary-expression before ‘)’ token
example.cxx: In member function ‘bool Bar<B>::concrete() [with B = Widget]’:
example.cxx:43: instantiated from here
example.cxx:30: error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘int’ to binary ‘operator<’
It seems like the compiler can't even parse this correctly, am I missing something here that makes that line completely bogus?
It seems like the compiler can't even parse this correctly, am I missing something here that makes that line completely bogus?
Yes. You need to use the template disambiguator:
return Foo<B>::template funcCall<5>();
// ^^^^^^^^
This way you will tell the compiler to parse the dependent name funcCall as the name of a member function template, and the subsequent angular brackets as delimiters for the corresponding template arguments.
Without it, funcCall will be parsed as the name of a data member, while < and > will be parsed as less-than and greater-than, respectively.

compiling errors related boost

When I use boost 1.52.1 and gcc-4.7.1 to compile my code, the following errors appear. It seems this is conflict between boost and c++ library.
Could some know how to resolve this problem?
Many thanks for your reply.
c:\program files\mingw64\bin\../lib/gcc/x86_64-w64-
mingw32/4.7.1/../../../../include/boost/math/policies
/error_handling.hpp: In function 'bool boost::math::policies::
detail::check_overflow(std::complex<T>,
R*, const char*, const Policy&)':c:\program
files\mingw64\bin\../lib/gcc/x86_64-w64 mingw32/4.7.1
/../../../../include/boost/math/policies/error_handling.hpp:583:11:
error: expected unqualified-id before numeric constant
c:\program files\mingw64\bin\../lib/gcc/x86_64-w64-mingw32
/4.7.1/../../../../include/boost/math/policies/error_handling.hpp:
584:49: error: lvalue required as unary '&' operand
c:\program files\mingw64\bin\../lib/gcc/x86_64-w64-mingw32/4.7.1/
../../../../include/boost/math/policies/
error_handling.hpp:584:107: error: 'im' was not declared in this
scope c:\program files\mingw64\bin\../lib/gcc/x86_64-w64-mingw32
/4.7.1/../../../../include/boost/math/policies/error_handling.
hpp: In function 'bool boost::math::policies::detail::
check_underflow(std::complex<T>, R*, const char*, const Policy&)':
c:\program files\mingw64\bin\../lib/gcc/x86_64-w64- mingw32
/4.7.1/../../../../include/boost/math/policies
/error_handling.hpp:602:11: error: expected unqualified-id before
numeric constant c:\program files\mingw64\bin\../lib/gcc/
x86_64-w64 mingw32/4.7.1/../../../../include/boost/math/policies
/error_handling.hpp:603:50: error: lvalue required as
unary '&' operand c:\program files\mingw64\bin\../lib/gcc/
x86_64-w64 mingw32/4.7.1/../../../../include/boost/math/policies
/error_handling .hpp:603:109: error: 'im' was not declared in
this scope c:\program files\mingw64\bin\../lib/gcc
/x86_64-w64-mingw32/4.7.1/../../../../include/boost/math/policies/
error_handling.hpp: In function 'bool boost::math::policies::
detail::check_denorm(std::complex<T>, R*, const char*,
const Policy&)':c:\program files\mingw64\bin\../lib/gcc
/x86_64-w64-mingw32/4.7.1/../../../../include/boost/
math/policies/error_handling.hpp:622:11: error: expected
unqualified-id before numeric constant
c:\program files\mingw64\bin\../lib/gcc/x86_64-w64-
mingw32/4.7.1/../../../../include/boost/math/policies/
error_handling.hpp:623:47: error: lvalue required as
unary '&' operand
c:\program files\mingw64\bin\../lib/gcc/x86_64-w64-
mingw32/4.7.1/../../../../include/boost/math/policies/
error_handling.hpp:623:103: error: 'im' was not declared
in this scope
The error appears in the code boost\math\policy\error_handling.hpp. But I am not sure when the program cite these functions. How does this error happen?
template <class R, class T, class Policy>
inline bool check_overflow(std::complex<T> val, R* result, const
char* function, const Policy& pol)
{
typedef typename R::value_type r_type;
r_type re, im;
bool r = check_overflow<r_type>(val.real(), &re, function, pol) || check_overflow<r_type>(val.imag(), &im, function, pol);
*result = R(re, im);
return r;
}
template <class R, class T, class Policy>
inline bool check_underflow(std::complex<T> val, R* result, const char* function, const Policy& pol)
{
typedef typename R::value_type r_type;
r_type re, im;
bool r = check_underflow<r_type>(val.real(), &re, function, pol) || check_underflow<r_type>(val.imag(), &im, function, pol);
*result = R(re, im);
return r;
}
Given this two functions and this noisy error message I can say that type that was used as parameter R doesn't defines value_type. Because of that, type r_type and variables im and re is not defined. As result you get error: 'im' was not declared in this scope error.
Using only provided code I can saw that type R has this requirements:
It must define type value_type
It must have constructor R(value_type real, value_type imagine)
All this means that you use some boost library that uses internaly check_underflow/check_overflow functions incorrectly, with incompatible template argument, I guess.

Extend boost::dynamic_bitset to add some functionality

I try to extend the boost::dynamic_bitset class with some functionality I need, such as counting bits after an AND operation, etc. Also I need access to the private members (m_num_bits, etc) because I want to be able to "override" the set() method to ensure the bitset's capacity with the resize() fct, if the pos of the bit to set is greater then the current bitset capacity. If I use the native set() fct it throughs an assertion error in that case (because the set() method does not resize in such case)
I am not very experienced with templates, also I am just getting back into C++ since a few weeks, it's a bit rusty, maybe somebody can help me out.
I started doing this:
template <typename Block, typename Allocator>
class ExtendedBitSet : public boost::dynamic_bitset<Block, Allocator> {
typedef boost::dynamic_bitset<Block, Allocator> super;
public:
void set(std::size_t pos) {
if (pos > super::size())
super::resize(pos);
set(pos);
}
bool get(std::size_t pos) const {
return super::test(pos);
}
};
// ...
ExtendedBitSet<> * bs = new ExtendedBitSet<>(128);
bs->set(33);
// ...
std::wcout << "Bit 48 is " << ((bs->get(48) == true) ? "true" : "false") << std::endl;
// ...
delete bs;
Ofcourse this is not compiling, the error is:
dynamic_bitset.cpp: In function ‘int main(int, char**)’:
dynamic_bitset.cpp:50: error: wrong number of template arguments (0, should be 2)
dynamic_bitset.cpp:7: error: provided for ‘template<class T, class Allocator> class ExtendedBitSet’
dynamic_bitset.cpp:50: error: invalid type in declaration before ‘=’ token
dynamic_bitset.cpp:50: error: wrong number of template arguments (0, should be 2)
dynamic_bitset.cpp:7: error: provided for ‘template<class T, class Allocator> class ExtendedBitSet’
dynamic_bitset.cpp:51: error: request for member ‘set’ in ‘* bs’, which is of non-class type ‘int’
..
dynamic_bitset.cpp:57: error: request for member ‘get’ in ‘* bs’, which is of non-class type ‘int’
Can somebody give a hint how to get that running? Also is there maybe a better way than deriving from the dynamic_bitset class or is this OK to do?
Any help is greatly appreciated.
Your ExtendedBitSet<> has no default parameters for the template type parameters and your code is trying to instantiate it without specifying them explicitly. Try using ExtendedBitSet<unsigned, std::allocator<unsigned> > bs instead.

What is causing this template-related compile error?

When I try to compile this:
#include <map>
#include <string>
template <class T>
class ZUniquePool
{
typedef std::map< int, T* > ZObjectMap;
ZObjectMap m_objects;
public:
T * Get( int id )
{
ZObjectMap::const_iterator it = m_objects.find( id );
if( it == m_objects.end() )
{
T * p = new T;
m_objects[ id ] = p;
return p;
}
return m_objects[ id ];
}
};
int main( int argc, char * args )
{
ZUniquePool< std::string > pool;
return 0;
}
I get this:
main.cpp: In member function ‘T* ZUniquePool<T>::Get(int)’:
main.cpp:12: error: expected `;' before ‘it’
main.cpp:13: error: ‘it’ was not declared in this scope
I'm using GCC 4.2.1 on Mac OS X.
It works in VS2008.
I'm wondering whether it might be a variation of this problem:
Why doesn't this C++ template code compile?
But as my error output is only partially similar, and my code works in VS2008, I am not sure.
Can anyone shed some light on what I am doing wrong?
You need typename:
typename ZObjectMap::const_iterator it = m_objects.find( id )
Since the type of ZObjectMap is dependent on the template parameter, the compiler has no clue what ZObjectMap::const_iterator is (it could be a member variable). You need to use typename to inform the compiler to assume it will be some sort of type.
Also to mention, GCC 4.5.0 gives the following output which would help you to solve the problem:
main.cpp: In member function 'T* ZUniquePool<T>::Get(int)':
main.cpp:12:7: error: need 'typename' before 'ZUniquePool<T>::ZObjectMap:: const_iterator' because 'ZUniquePool<T>::ZObjectMap' is a dependent scope
main.cpp:12:34: error: expected ';' before 'it'
main.cpp:13:11: error: 'it' was not declared in this scope
main.cpp: At global scope:
main.cpp:23:5: warning: second argument of 'int main(int, char*)' should be 'char **'

Template debugging in C++

I have a template class that is:
template <class identifier,class registeredObject>
class FxPairRegistry : public FxRegistry<pair<identifier,registeredObject> >
{
public:
registeredObject GetEntry(identifier, FxBool assertValue = true);
void RegisterInOrder(const pair<identifier,registeredObject> &ob);
typedef typename std::vector<pair<identifier,registeredObject> >::iterator iter;
};
I then have:
template <class identifier,class registeredObject>
registeredObject FxPairRegistry<identifier,registeredObject>::GetEntry(identifier id, FxBool
assertValue)
{
for (iterator iter = mRegistryList.begin(); iter != mRegistryList.end(); iter++)
{
if ((*iter).first == id)
{
return (*iter).second;
}
}
}
But I get errors like:
error: missing template arguments before 'iter'
error: expected `;' before 'iter'
error: expected primary-expression before '!=' token
error: 'mRegistryList' was not declared in this scope
error: expected primary-expression before '++' token
error: expected primary-expression before ')' token
error: expected primary-expression before ')' token
error: missing template arguments before 'iter'
error: expected `;' before 'iter'
error: expected primary-expression before '!=' token
error: 'mRegistryList' was not declared in this scope
error: expected primary-expression before '++' token
I dont quite get what I am doing wrong, but I am rusty a bit for sure....
It seems that here, you are typedef'ing a type called iter:
typedef typename std::vector<pair<identifier,registeredObject> >::iterator iter;
And then here:
iterator iter = mRegistryList.begin()
You are trying to define a variable called iter of type iterator, which (from the code you've shown) is not the name of any type that exists.
Check your for loop. What is iterator iter = ... supposed to do? You typedef'ed the iterators as iter so iter becomes the name of the type you want to declare.