Local class instances invalid template argument

Discussion in 'C++' started by Matthias, Jan 27, 2005.

  1. Matthias

    Matthias Guest

    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?

    --
    Regards,
    Matthias
    Matthias, Jan 27, 2005
    #1
    1. Advertising

  2. Matthias

    Matthias Guest

    Matthias wrote:
    > 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() );

    --
    Regards,
    Matthias
    Matthias, Jan 27, 2005
    #2
    1. Advertising

  3. Matthias

    Shezan Baig Guest

    Matthias wrote:
    > class Predicate
    > {
    > public:
    > bool operator() (...) {...}
    > };


    Make sure it takes the correct arguments.

    -shez-
    Shezan Baig, Jan 27, 2005
    #3
  4. Matthias

    Matthias Guest

    Shezan Baig wrote:
    > Matthias wrote:
    >
    >> class Predicate
    >> {
    >> public:
    >> bool operator() (...) {...}
    >> };

    >
    >
    > 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.

    --
    Regards,
    Matthias
    Matthias, Jan 27, 2005
    #4
  5. Hi,

    Matthias wrote:
    > 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:&hl=en&rnum=2
    ..
    ..
    Best regards,
    Bogdan Sintoma
    Bogdan Sintoma, Jan 27, 2005
    #5
  6. Matthias

    Matthias Guest

    Bogdan Sintoma wrote:
    > Hi,
    >
    > Matthias wrote:
    >
    >>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:&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.

    --
    Regards,
    Matthias
    Matthias, Jan 27, 2005
    #6
  7. Matthias

    Matthias Guest

    Matthias wrote:
    > Bogdan Sintoma wrote:
    >
    >> Hi,
    >>
    >> Matthias wrote:
    >>
    >>> 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:&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 :)

    --
    Regards,
    Matthias
    Matthias, Jan 27, 2005
    #7
  8. Matthias

    Matthias Guest

    Bogdan Sintoma wrote:
    > But, see the following link:
    > http://groups-beta.google.com/group...on author:&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 );
    }


    --
    Regards,
    Matthias
    Matthias, Jan 27, 2005
    #8
  9. Matthias wrote:
    > 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<T, bool>.

    > {
    > 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 ;).
    Bogdan Sintoma, Jan 27, 2005
    #9
  10. Matthias

    Matthias Guest

    Bogdan Sintoma wrote:
    > Matthias wrote:
    >
    >>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<T, bool>.
    >


    Why?

    >
    >>{
    >>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.


    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 :)

    --
    Regards,
    Matthias
    Matthias, Jan 27, 2005
    #10
  11. Matthias wrote:
    >> You should derive the FunctorBase from unary_function<T, bool>.

    >Why?

    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.


    >>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 :)


    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
    Bogdan Sintoma, Jan 28, 2005
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. karim
    Replies:
    1
    Views:
    752
    George Ter-Saakov
    Jun 26, 2003
  2. John Wohlbier
    Replies:
    2
    Views:
    349
    Josiah Carlson
    Feb 22, 2004
  3. nw
    Replies:
    0
    Views:
    296
  4. nguillot
    Replies:
    5
    Views:
    510
  5. Replies:
    1
    Views:
    1,008
Loading...

Share This Page