template class problem

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • jiake2007@gmail.com

    #1

    template class problem

    Hi all,

    I'm trying to write a template class that calls a function from one of
    its template parameters:

    template <class T>
    class Foo
    {
    public:
    Foo(T t): t(t) {}

    void doFoo() {
    t.doTheStuff();
    }

    private:
    T t;
    };


    The problem is: t.doTheStuff() obviously works only if T is non-
    pointer, and otherwise it has to be t->doTheStuff() .

    My question is: is there a way to implement a template class that
    would work with all types regardless of if T is a pointer or not?

    Thanks all,

    -J

  • mlimber

    #2
    Re: template class problem

    On Mar 1, 11:08 am, jiake2...@gmail .com wrote:
    I'm trying to write a template class that calls a function from one of
    its template parameters:
    >
    template <class T>
    class Foo
    {
    public:
    Foo(T t): t(t) {}
    >
    void doFoo() {
    t.doTheStuff();
    }
    >
    private:
    T t;
    >
    };
    >
    The problem is: t.doTheStuff() obviously works only if T is non-
    pointer, and otherwise it has to be t->doTheStuff() .
    >
    My question is: is there a way to implement a template class that
    would work with all types regardless of if T is a pointer or not?
    There are a number of ways to handle it. You could only pass objects,
    not pointer; you could specialize your class for T*; you could write
    an invoker class that is specialized for T and T*; you could convert
    your T member to use a smart pointer like std::tr1::share d_ptr (aka
    boost::shared_p tr) that accepts a custom deleter and set it to do
    nothing for incoming pointers but let it do things normally for copied
    values; etc. etc.

    Cheers! --M

    Comment

    • amparikh@gmail.com

      #3
      Re: template class problem

      On Mar 1, 8:08 am, jiake2...@gmail .com wrote:
      Hi all,
      >
      I'm trying to write a template class that calls a function from one of
      its template parameters:
      >
      template <class T>
      class Foo
      {
      public:
      Foo(T t): t(t) {}
      >
      void doFoo() {
      t.doTheStuff();
      }
      >
      private:
      T t;
      >
      };
      >
      The problem is: t.doTheStuff() obviously works only if T is non-
      pointer, and otherwise it has to be t->doTheStuff() .
      >
      My question is: is there a way to implement a template class that
      would work with all types regardless of if T is a pointer or not?
      >
      Thanks all,
      >
      -J
      Look up type traits and template specialization.


      Comment

      • John Harrison

        #4
        Re: template class problem

        jiake2007@gmail .com wrote:
        Hi all,
        >
        I'm trying to write a template class that calls a function from one of
        its template parameters:
        >
        template <class T>
        class Foo
        {
        public:
        Foo(T t): t(t) {}
        >
        void doFoo() {
        t.doTheStuff();
        }
        >
        private:
        T t;
        };
        >
        >
        The problem is: t.doTheStuff() obviously works only if T is non-
        pointer, and otherwise it has to be t->doTheStuff() .
        >
        My question is: is there a way to implement a template class that
        would work with all types regardless of if T is a pointer or not?
        >
        Thanks all,
        >
        -J
        >
        struct True {};
        struct False {};

        template <class T>
        struct IsAPointer
        {
        typedef False result;
        };

        template <class T>
        struct IsAPointer<T*>
        {
        typedef True result;
        };

        template <class T>
        class Foo
        {
        public:
        Foo(T t): t(t) {}

        void doFoo() {
        doFooHelper(typ ename IsAPointer<T>:: result());
        }

        private:
        T t;

        void doFooHelper(Tru e ptr)
        {
        t->doTheStuff() ;
        }

        void doFooHelper(Fal se ptr)
        {
        t.doTheStuff();
        }
        };

        Untested but something like that should work.

        Of course there are libraryies that already have stuff like IsAPointer
        written for you. You might want to look at type_traits at www.boost.org.

        john

        Comment

        • pedro

          #5
          Re: template class problem


          Hi again...

          I tried the following:
          (T and Key are template variables from the surrounding class)


          struct False {};
          struct True {};
          template<class Ustruct IsAPointer { typedef False result; };
          template<class Ustruct IsAPointer<U*{ typedef True result; };

          bool equals(T entry, Key key, False) { return entry.equals(ke y); }
          bool equals(T entry, Key key, True) { return entry->equals(key); }


          In principle this works, but when I do:

          if (equals(*tmp->data, key, typename IsAPointer<T>:: result()))

          later in the code, destructor for the pointed data gets called, which
          obviously is not the intention. What's wrong with the picture? How to
          get around this....

          Thanks again!

          -J

          Comment

          • John Harrison

            #6
            Re: template class problem

            pedro wrote:
            Hi again...
            >
            I tried the following:
            (T and Key are template variables from the surrounding class)
            >
            >
            struct False {};
            struct True {};
            template<class Ustruct IsAPointer { typedef False result; };
            template<class Ustruct IsAPointer<U*{ typedef True result; };
            >
            bool equals(T entry, Key key, False) { return entry.equals(ke y); }
            bool equals(T entry, Key key, True) { return entry->equals(key); }
            >
            >
            In principle this works, but when I do:
            >
            if (equals(*tmp->data, key, typename IsAPointer<T>:: result()))
            >
            later in the code, destructor for the pointed data gets called, which
            obviously is not the intention. What's wrong with the picture? How to
            get around this....
            >
            Thanks again!
            >
            -J
            >
            The pointed to data is of type T, is that right? And the destructor is
            called in the case when T is not a pointer? If that's the case then the
            destructor is being called because you are passing by value to the
            function equals (in other words its the parameter 'entry' that is being
            destructed). Change to a reference (preferably a const one).

            bool equals(const T& entry, Key key, False) { return entry.equals(ke y); }

            If I got that wrong you'll need to show me a bit more code.

            john

            Comment

            • pedro

              #7
              Re: template class problem


              Yep, that was it. I thought it has to be something like that, but
              seems I'm too tired to see by myself ;-)

              Anyway, problem solved. Thanks a lot!

              -J

              Comment

              Working...