member visibility in recursive class templates

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Christian E. Böhme

    member visibility in recursive class templates

    Hello all,

    I ran into a little problem with recursive templates that I am not sure
    what it has to do with, essentially, since I am currently limited in my
    access to compilers (namely GCC 4.1) and until now had no chance of testing
    the code with others. It may be an implementation detail or even in the
    standard (which I have no access to, unfortunately). Or maybe I have hit
    one of those cases whose solutions are "undefined" by the standard ...

    Anyway, here's the simplified code (the actual code is a lot more involved
    and may obfuscate the essentials):

    [code:


    #include <iostream>


    using namespace std;



    class my_float {

    public:

    my_float( float f ): m(f) {}

    float get() const { return m; }

    protected:

    float m;
    };


    class my_string {

    public:

    my_string( const char * s ): m(s) {}

    const char * get() const { return m; }

    protected:

    const char * m;
    };


    class my_type {

    public:

    my_type(): f(-.6457), s("fv6urtvku" ) {}
    my_type( float _f, const char * _s ): f(_f), s(_s) {}

    operator my_float () const { return f; }
    operator my_string () const { return s; }

    private:

    my_float f;
    my_string s;
    };


    // (1) recursion entry
    template < typename Value, typename Type1, typename Type2 >
    class my_recursion : public my_recursion<Va lue, Type2, int{

    protected:

    typedef my_recursion<Va lue, Type2, intbase_type;

    my_recursion( const Value & v ): base_type(v) {}

    public:

    operator Type1 () const { return value; }

    private:

    my_recursion();
    };

    // (2) partial spec for end of recursion and root of the inheritance tree
    template < typename Value, typename Type >
    class my_recursion<Va lue, Type, int{

    protected:

    my_recursion( const Value & v ): value(v) {}

    public:

    operator Type () const { return value; }

    protected:

    Value value;

    private:

    my_recursion();
    };

    // (3)
    template < typename Value >
    class my_class : public my_recursion<Va lue, my_float, my_string{
    public:

    typedef my_recursion<Va lue, my_float, my_stringbase_t ype;

    my_class( const Value & v ): base_type(v) {}
    };


    void ff( const my_float & f )
    {
    cout << "ff() = " << f.get() << endl;
    }

    void fs( const my_string & s )
    {
    cout << "fs() = " << s.get() << endl;
    }


    int main ( int argc, char ** argv )
    {
    my_type t(-.234354, "zzzdcghzzz z");
    my_class<my_typ emc(t);


    cout << "sizeof(my_floa t) = " << sizeof(my_float ) << endl
    << "sizeof(my_stri ng) = " << sizeof(my_strin g) << endl
    << "sizeof(my_type ) = " << sizeof(my_type) << endl
    << "sizeof(mc) = " << sizeof(mc) << endl;

    ff(mc);
    fs(mc);

    return 0;
    }


    --code end]

    What happened to me here is that value as defined as protected member variable
    in (2), though inherited by (1), is apparently not visible for the latter. The
    above written all by hand works perfectly and I suspect that the template class
    that is being inherited from in (1) is not consulted for possible inheritable
    members. It would be of great help if someone else could test the code with
    their compilers and what those complain (if at all).


    Thanks & regards,
    Christian
  • Thomas Tutone

    #2
    Re: member visibility in recursive class templates

    Christian E. Böhme wrote:
    I ran into a little problem with recursive templates that I am not sure
    what it has to do with, essentially, since I am currently limited in my
    access to compilers (namely GCC 4.1) and until now had no chance of testing
    the code with others. It may be an implementation detail or even in the
    standard (which I have no access to, unfortunately). Or maybe I have hit
    one of those cases whose solutions are "undefined" by the standard ...
    >
    Anyway, here's the simplified code (the actual code is a lot more involved
    and may obfuscate the essentials):
    >
    [code:
    >
    #include <iostream>
    using namespace std;
    [lots of code snipped]
    // (1) recursion entry
    template < typename Value, typename Type1, typename Type2 >
    class my_recursion : public my_recursion<Va lue, Type2, int{
    protected:
    typedef my_recursion<Va lue, Type2, intbase_type;
    my_recursion( const Value & v ): base_type(v) {}
    public:
    operator Type1 () const { return value; }
    Change the above line to:
    operator Type1 () const { return base_type::valu e; }

    [snip]

    Best regards,

    Tom

    Comment

    • Christian E. Böhme

      #3
      Re: member visibility in recursive class templates

      Thomas Tutone wrote:
      >>public:
      > operator Type1 () const { return value; }
      >
      >
      Change the above line to:
      operator Type1 () const { return base_type::valu e; }
      That's no solution anyway because it doesn't scale -- at all.
      It works for that particular example as there is only one recursion
      but then again I would not possibly have to use recursion for a single
      inheritance, would I ? The actual code may have (countably) many of
      them. It works nicely with a slightly modified version which has its
      own shortcomings with the compiler _I_ used, though. If it had applied
      slightly more brain into its code generation then I would not have bothered
      with checking out the above aproach. Which compiler did you use ? What
      does the standard say ?


      Regards,
      Christian

      Comment

      • Thomas Tutone

        #4
        Re: member visibility in recursive class templates

        Christian E. Böhme wrote:
        Thomas Tutone wrote:
        >
        >public:
        operator Type1 () const { return value; }

        Change the above line to:
        operator Type1 () const { return base_type::valu e; }
        >
        That's no solution anyway because it doesn't scale -- at all.
        It works for that particular example as there is only one recursion
        but then again I would not possibly have to use recursion for a single
        inheritance, would I ? The actual code may have (countably) many of
        them. It works nicely with a slightly modified version which has its
        own shortcomings with the compiler _I_ used, though. If it had applied
        slightly more brain into its code generation then I would not have bothered
        with checking out the above aproach. Which compiler did you use ? What
        does the standard say ?
        First, I used the Comeau on-line compiler, and you should too:



        Second, you seem to be missing the point. If you are using templates,
        then you MUST qualify the name of the reference to the member of a base
        class. The recursion is just a red herring. Let's take a much
        simplified example:

        template<typena me T>
        struct Derived : public T {
        int func() { value; } // line 3
        };

        struct Parent {
        int value;
        };

        int main()
        {
        Derived<Parentd ;
        d.func();
        }

        Try to compile it, and you'll get a compile error in line 3: value is
        undefined. Now let's try that again, with just line 3 changed:

        template<typena me T>
        struct Derived : public T {
        int func() { return T::value; } // line 3
        };

        struct Parent {
        int value;
        };

        int main()
        {
        Derived<Parentd ;
        d.func();
        }

        Now it compiles cleanly. You see? You MUST qualify your reference to
        a member of the parent class if you are using templates. Focus on that
        part before you move on to the recursion, which I don't think is
        relevant to your question.

        Best regards,

        Tom

        Comment

        • Thomas Tutone

          #5
          Re: member visibility in recursive class templates


          Thomas Tutone wrote:

          [snip]

          Sorry, I had a typo in the first example. Let's try it again.
          Second, you seem to be missing the point. If you are using templates,
          then you MUST qualify the name of the reference to the member of a base
          class. The recursion is just a red herring. Let's take a much
          simplified example:
          template<typena me T>
          struct Derived : public T {
          int func() { return value; } // line 3
          // *** Note correction in above line!
          };

          struct Parent {
          int value;
          };

          int main()
          {
          Derived<Parentd ;
          d.func();
          }
          Try to compile it, and you'll get a compile error in line 3: value is
          undefined. Now let's try that again, with just line 3 changed:
          >
          template<typena me T>
          struct Derived : public T {
          int func() { return T::value; } // line 3
          };

          struct Parent {
          int value;
          };

          int main()
          {
          Derived<Parentd ;
          d.func();
          }
          Now it compiles cleanly. You see? You MUST qualify your reference to
          a member of the parent class if you are using templates. Focus on that
          part before you move on to the recursion, which I don't think is
          relevant to your question.
          Best regards,

          Tom

          Comment

          • Kai-Uwe Bux

            #6
            Re: member visibility in recursive class templates

            "Christian E. Böhme" wrote:
            Hello all,
            >
            I ran into a little problem with recursive templates that I am not sure
            what it has to do with, essentially, since I am currently limited in my
            access to compilers (namely GCC 4.1) and until now had no chance of
            testing
            the code with others. It may be an implementation detail or even in the
            standard (which I have no access to, unfortunately). Or maybe I have hit
            one of those cases whose solutions are "undefined" by the standard ...
            [snip]
            // (1) recursion entry
            template < typename Value, typename Type1, typename Type2 >
            class my_recursion : public my_recursion<Va lue, Type2, int{
            >
            protected:
            >
            typedef my_recursion<Va lue, Type2, intbase_type;
            >
            my_recursion( const Value & v ): base_type(v) {}
            >
            public:
            >
            operator Type1 () const { return value; }
            [snip]

            For me,

            operator Type1 () const { return this->value; }

            works. It's a dependent name lookup thing: you are up against the standard,
            not against the compiler.


            Best

            Kai-Uwe Bux

            Comment

            • Christian E. Böhme

              #7
              Re: member visibility in recursive class templates

              Thomas Tutone wrote:
              First, I used the Comeau on-line compiler, and you should too:
              >
              http://www.comeaucomputing.com/tryitout/
              Nice exercise but nothing I can do actual work (read: code generation)
              with. Also: LINUX/ELF != LINUX/Intel. Plus (or Minus if you will): None
              of the backends I need. Not even the host platform to run it on. Also,
              it's not even a native optimizing compiler (they have to resort to the
              native C compiler on the target platform for actual code generation).
              So, why would I want to use it, then ;-) I actually started to wonder
              what these "largest supercomputers" are which their compilers are supposed
              to run on given the host/target list they posted. Also, I have never seen
              the statement that C++ is a dialect of C. I was under the impression that
              it's a superset of it.
              Second, you seem to be missing the point. If you are using templates,
              then you MUST qualify the name of the reference to the member of a base
              class.
              See, that is the kind of hint I was trying to find. If only you could point
              me to the actual _rationale_ of that capital "MUST" it might even be the info
              I was looking for (re: The Standard).
              The recursion is just a red herring.
              Nope. It's the whole point of the code. Having to refer to the root of
              the inheritance tree is possible but rather unelegant and (as with some
              other constructs) actually working around the inconsistencies in the
              language which has never been a fine time.
              Now it compiles cleanly. You see? You MUST qualify your reference to
              That's actually the easiest part. I usually have to look at the code that
              is being generated to find the optimum source solution using profiling data.
              May I speculate that if you would have taken the time to read the OP, you'd
              have noticed that I posted the amount of code for some reason, namely to have
              someone actually understand what I was doing and ideally point me to the
              rationale (or the section/paragraph if that existed) that prevented me
              from what I was doing. It's always the why that matters.


              Thanks & regards,
              Christian

              Comment

              • Thomas Tutone

                #8
                Re: member visibility in recursive class templates


                Christian E. Böhme wrote:
                Thomas Tutone wrote:
                >
                First, I used the Comeau on-line compiler, and you should too:
                >
                http://www.comeaucomputing.com/tryitout/
                >
                Nice exercise but nothing I can do actual work (read: code generation)
                with. Also: LINUX/ELF != LINUX/Intel. Plus (or Minus if you will): None
                of the backends I need. Not even the host platform to run it on. Also,
                it's not even a native optimizing compiler (they have to resort to the
                native C compiler on the target platform for actual code generation).
                So, why would I want to use it, then ;-) I actually started to wonder
                what these "largest supercomputers" are which their compilers are supposed
                to run on given the host/target list they posted. Also, I have never seen
                the statement that C++ is a dialect of C. I was under the impression that
                it's a superset of it.
                >
                Second, you seem to be missing the point. If you are using templates,
                then you MUST qualify the name of the reference to the member of a base
                class.
                >
                See, that is the kind of hint I was trying to find. If only you could point
                me to the actual _rationale_ of that capital "MUST" it might even be the info
                I was looking for (re: The Standard).
                >
                The recursion is just a red herring.
                >
                Nope. It's the whole point of the code. Having to refer to the root of
                the inheritance tree is possible but rather unelegant and (as with some
                other constructs) actually working around the inconsistencies in the
                language which has never been a fine time.
                >
                Now it compiles cleanly. You see? You MUST qualify your reference to
                >
                That's actually the easiest part. I usually have to look at the code that
                is being generated to find the optimum source solution using profiling data.
                May I speculate that if you would have taken the time to read the OP, you'd
                have noticed that I posted the amount of code for some reason, namely to have
                someone actually understand what I was doing and ideally point me to the
                rationale (or the section/paragraph if that existed) that prevented me
                from what I was doing. It's always the why that matters.
                Dude, you must be a lot of fun at parties.

                I take it you're being deliberately obtuse.

                Just in case you're not:

                1. I wasn't suggesting you switch to Comeau (although there are worse
                things you could do), I was suggesting that when you have a question
                about whether your compiler is correctly rejecting your code, test it
                out on Comeau's online compiler. That's what many of the experts do.

                2. I wasn't suggesting that the template recursion was irrelevant to
                your project, I was pointing out that it had nothing to do with the
                error you were getting.

                By the way, in case you didn't see it, Kai-Uwe Bux posted another
                solution to your problem. Perhaps his way will scale better.

                Good luck with your project.

                Best regards,

                Tom

                Comment

                • Sumit Rajan

                  #9
                  Re: member visibility in recursive class templates

                  Kai-Uwe Bux wrote:
                  "Christian E. Böhme" wrote:
                  >
                  >Hello all,
                  >>
                  >I ran into a little problem with recursive templates that I am not sure
                  >what it has to do with, essentially, since I am currently limited in my
                  >access to compilers (namely GCC 4.1) and until now had no chance of
                  >testing
                  >the code with others. It may be an implementation detail or even in the
                  >standard (which I have no access to, unfortunately). Or maybe I have hit
                  >one of those cases whose solutions are "undefined" by the standard ...
                  [snip]
                  >// (1) recursion entry
                  >template < typename Value, typename Type1, typename Type2 >
                  >class my_recursion : public my_recursion<Va lue, Type2, int{
                  >>
                  >protected:
                  >>
                  > typedef my_recursion<Va lue, Type2, intbase_type;
                  >>
                  > my_recursion( const Value & v ): base_type(v) {}
                  >>
                  >public:
                  >>
                  > operator Type1 () const { return value; }
                  [snip]
                  >
                  For me,
                  >
                  operator Type1 () const { return this->value; }
                  >
                  works. It's a dependent name lookup thing: you are up against the standard,
                  not against the compiler.
                  >
                  For more info on this the OP could check out:


                  Regards,
                  Sumit.

                  Comment

                  • Clark S. Cox III

                    #10
                    Re: member visibility in recursive class templates

                    Christian E. Böhme wrote:
                    Thomas Tutone wrote:
                    >
                    >>public:
                    >> operator Type1 () const { return value; }
                    >>
                    >>
                    >Change the above line to:
                    > operator Type1 () const { return base_type::valu e; }
                    >
                    That's no solution anyway because it doesn't scale -- at all.
                    Then use:

                    operator Type1 () const { return this->value; }
                    It works for that particular example as there is only one recursion
                    but then again I would not possibly have to use recursion for a single
                    inheritance, would I ? The actual code may have (countably) many of
                    them. It works nicely with a slightly modified version which has its
                    own shortcomings with the compiler _I_ used, though.
                    This is not an issue with your compiler; it is behaving in a standard
                    compliant manner. Any standard compliant compiler will do the same.
                    If it had applied slightly more brain into its code generation then I
                    would not have bothered with checking out the above aproach. Which
                    compiler did you use ? What does the standard say ?
                    Check out the FAQ for more information:



                    --
                    Clark S. Cox III
                    clarkcox3@gmail .com

                    Comment

                    Working...