By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,238 Members | 1,787 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,238 IT Pros & Developers. It's quick & easy.

function object to query STL containers

P: n/a
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=g filt=================
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

Jul 23 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
jsnX wrote:
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,

--
Ney André de Mello Zunino
Jul 23 '05 #2

P: n/a
"jsnX" <ja*********@gmail.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com
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;
}
};
--
John Carson

Jul 23 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.