473,386 Members | 1,706 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

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<Value, Type2, int{

protected:

typedef my_recursion<Value, 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<Value, 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<Value, my_float, my_string{
public:

typedef my_recursion<Value, my_float, my_stringbase_type;

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, "zzzdcghzzzz");
my_class<my_typemc(t);
cout << "sizeof(my_float) = " << sizeof(my_float) << endl
<< "sizeof(my_string) = " << sizeof(my_string) << 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
Oct 9 '06 #1
9 2273
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<Value, Type2, int{
protected:
typedef my_recursion<Value, 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::value; }

[snip]

Best regards,

Tom

Oct 9 '06 #2
Thomas Tutone wrote:
>>public:
operator Type1 () const { return value; }


Change the above line to:
operator Type1 () const { return base_type::value; }
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
Oct 9 '06 #3
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::value; }

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:

http://www.comeaucomputing.com/tryitout/

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

Oct 9 '06 #4

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

Oct 10 '06 #5
"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<Value, Type2, int{

protected:

typedef my_recursion<Value, 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
Oct 10 '06 #6
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
Oct 10 '06 #7

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

Oct 10 '06 #8
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<Value, Type2, int{

protected:

typedef my_recursion<Value, 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:
http://www.parashift.com/c++-faq-lit...html#faq-35.19

Regards,
Sumit.
Oct 10 '06 #9
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::value; }

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:

http://www.parashift.com/c++-faq-lit...html#faq-35.19

--
Clark S. Cox III
cl*******@gmail.com
Oct 10 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Dave | last post by:
Hello all, I am trying to create a full specialization of a member function template of a class template. I get the following errors: Line 29: 'foo<T1>::bar' : illegal use of explicit...
5
by: Levent | last post by:
Hi, Why doesn't this work? (tried with gcc 3.3.3 and VC++ 7.1): #include <iostream> template<class T, unsigned N> struct Foo { void func(); }; template<class T, unsigned N>
9
by: Ian | last post by:
Can it be done? If so, what's the syntax. For example a full specialisation, template <typename T> struct X { template <typename C> void foo( C a ) {} };
6
by: Nick Stansbury | last post by:
Hi, I have a loop running on Page_PreRender that sets a number of controls to invisible based on a set of criteria. Before I do this however, I set all of the drop down lists to be visible with...
4
by: Joseph Turian | last post by:
Hi, What is the correct syntax to get the bar<T>::f<int, unsigned>() function to compile in the following fragment? Thanks, Joseph class foo {
16
by: Fir5tSight | last post by:
Hi All, I have a small C#.NET program that is as follows: using System; class A { protected int x = 123; }
52
by: Ben Voigt [C++ MVP] | last post by:
I get C:\Programming\LTM\devtools\UselessJunkForDissassembly\Class1.cs(360,27): error CS0535: 'UselessJunkForDissassembly.InvocableInternals' does not implement interface member...
15
by: akomiakov | last post by:
Is there a technical reason why one can't initialize a cost static non- integral data member in a class?
4
by: andreyvul | last post by:
I have a template function like this: std::vector<std::pair<Square<T>, Triangle<T * recarrow(T a, T b, int n) { /* ... */ } template <class T> struct Square { /* ... */ };
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.