function object to query STL containers

J

jsnX

i want a function object that is
a) initialized with an STL container foo
b) will search foo for an object of type foo::value_type

here is my code:

========================================================================
/* if we have a big list of things, and we went to check it
* over and over for this or that thing, then we can use this
* object to cache the list and consolidate queries of it.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 template<class T>
17 class is_in : public unary_function<T::value_type, bool>
18 {
19 private:
20 T::iterator a;
21 T::iterator z;
22
23 public:
24 is_in(const T& t) : a( t.begin() ), z( t.end() )
25 {}
26
27 is_in(const T::iterator& a, const T::iterator& z ) : a(a), z(z)
28 {}
29
30 bool
31 operator() (const T::value_type& tau)
32 {
33 return std::find(a, z, tau) != z;
34 }
35 };
=======================================================================

however, this code does not compile:

====================error=messages=piped=through=gfilt=================
gfilt -ansi is_in.cpp
BD Software STL Message Decryptor v2.47 for gcc
is_in.cpp:17: error: expected template-name before '<
' token
is_in.cpp:17: error: expected `{' before '<
' token
is_in.cpp:17: error: expected unqualified-id before '<
' token
is_in.cpp:17: error: expected `;' before '<
' token
Process gfilt exited with code 1
=======================================================================

can someone tell me why my code won't go? it certainly *looks* legal.

thanks,

_jsnX
 
?

=?ISO-8859-1?Q?Ney_Andr=E9_de_Mello_Zunino?=

jsnX said:
can someone tell me why my code won't go? it certainly *looks* legal.

Try the following modified version (notice mainly the addition of the
std:: prefix for unary_function and the use of 'typename'):

#include <functional>

template<class T>
class is_in : public std::unary_function<typename T::value_type, bool>
{
private:
typename T::iterator a;
typename T::iterator z;

public:
is_in(const T& t) : a( t.begin() ), z( t.end() )
{}

is_in(const typename T::iterator& a, const typename T::iterator& z
) : a(a), z(z)
{}

bool
operator() (const typename T::value_type& tau)
{
return std::find(a, z, tau) != z;
}
};

Hope that helps,
 
J

John Carson

jsnX said:
i want a function object that is
a) initialized with an STL container foo
b) will search foo for an object of type foo::value_type

here is my code:

========================================================================
/* if we have a big list of things, and we went to check it
* over and over for this or that thing, then we can use this
* object to cache the list and consolidate queries of it.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16 template<class T>
17 class is_in : public unary_function<T::value_type, bool>
18 {
19 private:
20 T::iterator a;
21 T::iterator z;
22
23 public:
24 is_in(const T& t) : a( t.begin() ), z( t.end() )
25 {}
26
27 is_in(const T::iterator& a, const T::iterator& z ) : a(a),
z(z) 28 {}
29
30 bool
31 operator() (const T::value_type& tau)
32 {
33 return std::find(a, z, tau) != z;
34 }
35 };
=======================================================================

however, this code does not compile:

Please don't include line numbers in your post. Anyone wishing to compile
your code has to remove them, which is a pain.

Your basic problem is that you haven't used the keyword typename to indicate
that, for example, T::value_type represents a type rather than a variable
name. What is obvious to you isn't always obvious to the compiler. To quote
from Vandvoorde and Josuttis (C++ Templates: The Complete Guide, p. 43): "In
general, typename has to be used whenever a name that depends on a template
parameter is a type."

The complete rules are a little more complicated (discussed by the same
authors from p.130 onward). Specifically, you must use use typename if the
following four conditions are satisfied:

1. The name appears in a template.
2. The name is qualified (i.e., uses either the scope resolution operator ::
or this->).
3. The name does *not* occur in a list of base classes when declaring a
derived class and does *not* appear in a list of member initialisers for a
constructor.
4. The name is dependant on a type parameter.

Item 3 is tricky. As far as I can work out, occurrence of the name in a list
of base classes or member initialisers only counts if it is at the
"outermost level", so that the qualified name actually is a base class.
Consider the following:

template <class T>
struct X
{
struct Base
{
T t;
};
};

template <class S>
class Derived : public X<S>::Base
{};

X<S>::Base is actually a base class of Derived, so typename is not required
in front of X<S>::Base. However, in your code:

template<class T>
class is_in : public unary_function<T::value_type, bool>

T::value_type is NOT a base class of is_in, so typename is required.

Warning: in case you are thinking of always putting in typename just in
case, typename is illegal unless conditions 1-3 are met. Thus

template <class S>
class Derived : public typename X<S>::Base
{};

is illegal.


This compiles:

template<class T>
class is_in : public std::unary_function<typename T::value_type, bool>
{
private:
typename T::iterator a;
typename T::iterator z;

public:
is_in(const T& t) : a( t.begin() ), z( t.end() )
{}

is_in(const typename T::iterator& a, const typename T::iterator& z ) :
a(a), z(z)
{}

bool
operator() (const typename T::value_type& tau)
{
return std::find(a, z, tau) != z;
}
};
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top