Local class instances invalid template argument

M

Matthias

Hello,

I thought one major advantage of using functors as e.g. sorting
predicates over functions would be that I can do something like this:

void foo()
{
class Predicate
{
public:
bool operator() (...) {...}
};

std::list<whatever> lst;
// ...
std::transform( lst.begin(), lst.end(), lst.begin(), Predicate() );
}

However, I am getting a compile time error "type foo()::predicate
composed from a local class is not a valid template-argument".

Why?
 
M

Matthias

Matthias said:
Hello,

I thought one major advantage of using functors as e.g. sorting
predicates over functions would be that I can do something like this:

void foo()
{
class Predicate
{
public:
bool operator() (...) {...}
};

std::list<whatever> lst;
// ...
std::transform( lst.begin(), lst.end(), lst.begin(), Predicate() );
}

However, I am getting a compile time error "type foo()::predicate
composed from a local class is not a valid template-argument".

Why?

Whoops, this should read:

lst.sort( ..., Predicate() );
 
M

Matthias

Shezan said:
Make sure it takes the correct arguments.

-shez-

When taking the exact same class outside the function scope, everything
works just fine. I doubt it had something to do with the arguments.
 
B

Bogdan Sintoma

Hi,
Hello,

I thought one major advantage of using functors as e.g. sorting
predicates over functions would be that I can do something like this:

void foo()
{
class Predicate
{
public:
bool operator() (...) {...}
};

std::list<whatever> lst;
// ...
std::transform( lst.begin(), lst.end(), lst.begin(), Predicate() );
}

However, I am getting a compile time error "type foo()::predicate
composed from a local class is not a valid template-argument".

Why?
Because the standard say so:

14.3.1 paragraph 2:
"A local type, a type with no linkage, an unnamed type or a type
compounded from any of these types shall not be used as a
templateargument for a template typeparameter.
[Example:
template <class T> class X { /* ... */ };
void f()
{
struct S { /* ... */ };
X<S> x3; // error: local type used as templateargument
X<S*> x4; // error: pointer to local type used as templateargument
}
-end example] [Note: a template type argument may be an incomplete
type (3.9). ]"

But, see the following link:
http://groups-beta.google.com/group...on+author:[email protected]&hl=en&rnum=2
..
..
Best regards,
Bogdan Sintoma
 
M

Matthias

Bogdan said:
Hi,
Hello,

I thought one major advantage of using functors as e.g. sorting
predicates over functions would be that I can do something like this:

void foo()
{
class Predicate
{
public:
bool operator() (...) {...}
};

std::list<whatever> lst;
// ...
std::transform( lst.begin(), lst.end(), lst.begin(), Predicate()
);

}

However, I am getting a compile time error "type foo()::predicate
composed from a local class is not a valid template-argument".

Why?

Because the standard say so:

14.3.1 paragraph 2:
"A local type, a type with no linkage, an unnamed type or a type
compounded from any of these types shall not be used as a
templateargument for a template typeparameter.
[Example:
template <class T> class X { /* ... */ };
void f()
{
struct S { /* ... */ };
X<S> x3; // error: local type used as templateargument
X<S*> x4; // error: pointer to local type used as templateargument
}
-end example] [Note: a template type argument may be an incomplete
type (3.9). ]"

But, see the following link:
http://groups-beta.google.com/group...on+author:[email protected]&hl=en&rnum=2
.
.
Best regards,
Bogdan Sintoma

Ah, that's clever, in fact simply making the local type also a non-local
type by subtyping it from a non-local type.
I wonder if you need the additional overhead this delegation produces at
all. Couldn't you just inherit from an empty non-local class? That would
make your type non-local as well, and you wouldn't have to do that
delegation stuff... Just an idea.
 
M

Matthias

Matthias said:
Bogdan said:
Hi,
Hello,

I thought one major advantage of using functors as e.g. sorting
predicates over functions would be that I can do something like this:

void foo()
{
class Predicate
{
public:
bool operator() (...) {...}
};

std::list<whatever> lst;
// ...
std::transform( lst.begin(), lst.end(), lst.begin(), Predicate()

);

}

However, I am getting a compile time error "type foo()::predicate
composed from a local class is not a valid template-argument".

Why?

Because the standard say so:

14.3.1 paragraph 2:
"A local type, a type with no linkage, an unnamed type or a type
compounded from any of these types shall not be used as a
templateargument for a template typeparameter.
[Example:
template <class T> class X { /* ... */ };
void f()
{
struct S { /* ... */ };
X<S> x3; // error: local type used as templateargument
X<S*> x4; // error: pointer to local type used as templateargument
}
-end example] [Note: a template type argument may be an incomplete
type (3.9). ]"

But, see the following link:
http://groups-beta.google.com/group...on+author:[email protected]&hl=en&rnum=2

.
.
Best regards,
Bogdan Sintoma

Ah, that's clever, in fact simply making the local type also a non-local
type by subtyping it from a non-local type.
I wonder if you need the additional overhead this delegation produces at
all. Couldn't you just inherit from an empty non-local class? That would
make your type non-local as well, and you wouldn't have to do that
delegation stuff... Just an idea.

Ah yes of course, nevermind. Got a misunderstanding there, but hey, it
works :)
 
M

Matthias

Bogdan said:
But, see the following link:
http://groups-beta.google.com/group...on+author:[email protected]&hl=en&rnum=2
.
.
Best regards,
Bogdan Sintoma

Hm, I am getting an error:
localclass.cpp: In constructor `FunctorWrapper<T>::FunctorWrapper(const
FunctorBase<T>&) [with T = int]':
localclass.cpp:39: instantiated from here
localclass.cpp:17: error: invalid initialization of reference of type '
FunctorBase<int>&' from expression of type 'const FunctorBase<int>'

Here is the code (I have taken out the abstraction of the return type):

template<typename T>
class FunctorBase
{
public:
virtual bool operator() ( const T& ) const = 0;
};

template<typename T>
class FunctorWrapper
{
FunctorBase<T>& _functor;
public:
FunctorWrapper( const FunctorBase<T>& rf )
: _functor(rf) {}

bool operator() ( const T& t ) const {
return _functor(t);
}
};


int main()
{
std::list<int> l;


class Functor: public FunctorBase<int>
{
public:
bool operator() (const int& n) const {
return true;
}
};

Functor f;
FunctorWrapper<int> w(f);

std::transform( l.begin(), l.end(), l.begin(), w );
}
 
B

Bogdan Sintoma

Matthias said:
Here is the code (I have taken out the abstraction of the return type):

template<typename T>
class FunctorBase
You should derive the FunctorBase from unary_function said:
{
public:
virtual bool operator() ( const T& ) const = 0;
};

template<typename T>
class FunctorWrapper
{
FunctorBase<T>& _functor;
public:
FunctorWrapper( const FunctorBase<T>& rf )
Here is the problem: ^^^
Either you store your _functor as a const reference either you modify
the constructor to receive a non-const reference. And avoid the leading
underscore ;).
 
M

Matthias

Bogdan said:
You should derive the FunctorBase from unary_function<T, bool>.

Why?


Here is the problem: ^^^
Either you store your _functor as a const reference either you modify
the constructor to receive a non-const reference.

Oh, of course :) Thanks.

And avoid the leading
underscore ;).

Why? It's my way of notating a member variable. This way you directly
see which variable is a member and which is not. I used to use m_ but _
is shorter :)
 
B

Bogdan Sintoma

Matthias said:
Again, because the c++ standard say so ;)
Chapter 20.3 paragraph 5.
"To enable adaptors and other components to manipulate function objects
that take one or two arguments it is required that the function objects
correspondingly provide typedefs argument_type and result_type for
function objects that take one argument and first_argument_type,
second_argument_type, and result_type for function objects that take
two arguments."

You can just provide those typedefs, but that's exactly what
unary_function is for.

Why? It's my way of notating a member variable. This way you directly
see which variable is a member and which is not.
I used to use m_ but _ is shorter :)

According to the standard:
"17.4.3.1.2 Global names
1 Certain sets of names and function signatures are always reserved to
the implementation:
- Each name that contains a double underscore (_ _) or begins with an
underscore followed by an uppercase letter (2.11) is reserved to the
implementation for any use.
- Each name that begins with an underscore is reserved to the
implementation for use as a name in the
global namespace.165)"

So, not every name that start with an underscore is restricted, but it
is more easy to avoid leading underscore than to keep in mind all of
above :).

....
Bogdan
 

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,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top