C++ and typedefs

77078a51228688ee3cc87e539c4ff235
0
Faelenor 101 Sep 06, 2005 at 17:38

Here is some code:

class A
{
};
 
class A2
{
};
 
class B : public A
{
private:
  typedef A super;
  typedef A2 not_super;
};
 
class C : public B
{
private:
  typedef B super;
 
public:
  void Method()
  {
    super::super  x;
    super::not_super y;
  }
};

I think that both lines of code in C::Method() shouldn’t compile. In code warrior, this is the case, but in more complex classes, it seems that super::super is allowed! that’s weird. In VC++, super::super compiles, but VC++ is not a reference…

Do you know if it should compile or not?

Thx,

-Francis

13 Replies

Please log in or register to post a reply.

8e156032c689e2c371468d2a2f223db8
0
Kippesoep 101 Sep 06, 2005 at 18:53

It shouldn’t compile with the typedefs being private in B. If they were public or protected, it should compile just fine.

77078a51228688ee3cc87e539c4ff235
0
Faelenor 101 Sep 06, 2005 at 19:51

Yeah I know… It was a bad question. I mean, do you know why two compilers seem to have troubles or to be very permissive with this?

C764aeb3b32e1a4cfe4029972c763097
0
tob 101 Sep 06, 2005 at 22:26

It’s probably a standards support problem. gcc 3.3 outputs the following:

bla.cpp: In member function `void C::Method()’:
bla.cpp:23: error: `typedef class A B::super’ is private
bla.cpp:47: error: within this context
bla.cpp:25: error: `typedef class A2 B::not_super’ is private
bla.cpp:49: error: within this context

Which version of VC++ do you use?

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Sep 07, 2005 at 08:30

VC++ 7.1 gives a compile error, as it should:

main.cpp(25) : error C2248: 'B::not_super' : cannot access private typedef declared in class 'B'
        main.cpp(13) : see declaration of 'B::not_super'
        main.cpp(9) : see declaration of 'B'

And, if you need a standard reference, use The online compiler of Comeau

.edit: never mind, I disabled language extensions, with these extensions enabled it compiles fine.

Da26e799270ce5e8b62659ed77b11cef
0
Axel 101 Sep 07, 2005 at 10:23

I don’t think Comeau is more standard compliant than .NET 2003. It supports “the whole language” (it supports “export”), but that doesn’t mean it has bugs too ;)

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Sep 07, 2005 at 10:34

Excuse me? :D
Comeau is definitely more standard compliant than VC++ 2003. That’s because comeau strives to be standard compliant, and it will fix bugs on short notice if something turns out to be non-standard. VC++ doesn’t claim to be standard compliant and it will definitely not try to accomplish that.

Furthermore, by many experts and even people in the committee, comeau is seen as -the- standard compliant compiler. Now that means something, in my opionion :)

And btw, export isn’t the only difference between comean and VC++. For example, this compiles in VC++ while it shouldn’t (why?)

struct A
{
    typedef int mytype;
    template<class T> struct mytemplate { };
};

template<class T> struct S
{
    void bla()
    {
    T::mytype a;
    T::mytemplate<int> b;
    }
};

Another example: this gives wrong results under VC++ (why?)

#include <iostream>

void func(char)
{
    std::cout << "func(char)" << std::endl;
}

template<class T> void tfunc(const T & t)
{
    func(t);
}

void func(int)
{
    std::cout << "func(int)" << std::endl;
}

int main()
{
    char c = 0;
    int i = 0;
    tfunc(c);
    tfunc(i);
}
77078a51228688ee3cc87e539c4ff235
0
Faelenor 101 Sep 07, 2005 at 11:14

tob: I’m using VC++ 7.1

.oisyn: I know, this line doesn’t compile on any compiler. But both lines shouldn’t compile! So VC++ 7.1 is wrong, again!

Axel: VC++ 7.1 is indeed far from being bug free! (I hope that there was a missing “no” in your post).

46407cc1bdfbd2db4f6e8876d74f990a
0
Kenneth_Gorking 101 Sep 08, 2005 at 16:07

For example, this compiles in VC++ while it shouldn’t (why?)

Why shouldn’t this compile?

Another example: this gives wrong results under VC++ (why?)

I got this:

func(char)
func(int)

Seems about right…

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Sep 09, 2005 at 07:33

I was hoping someone would reply :wink:

Why shouldn’t this compile?

T is a template type, you don’t know what T::mytype is until you know the actual T. But the compiler needs to parse the template code before any template instantiation is done. So the standard dictates that the compiler should assume it’s an identifier (function, variable, enum value, whatever) and not a type. You need to tell the compiler it’s a typename using the typename keyword:

typename T::mytype a;

The same goes for the template, in my example it’s obvious what it should be, but what if the template argument was a value instead of a type, like this:

T::mytemplate<3> b;

That could parse as a variable definition or a simple expression: test if the value of t::mytemplate is smaller than 3, and the result of that is smaller than b.
Therefore, next to the typename discussed earlier, you also need to specify a template:

typename T::template mytype<3> b;

Another example: this gives wrong results under VC++ (why?)
I got this:

func(char)
func(int)

Seems about right…

Wrong again, func(int) wasn’t defined until after the definition of tfunc. Therefore, it shouldn’t be considered in the list of possible overloads to call when tfunc calls func. func(char) should be called twice.

22b3033832c5c699c856814b0cf80cb1
0
bladder 101 Sep 09, 2005 at 12:27

Wrong again, func(int) wasn’t defined until after the definition of tfunc. Therefore, it shouldn’t be considered in the list of possible overloads to call when tfunc calls func. func(char) should be called twice.

intresting, I didn’t know this one. Are you sure this is supposed to happen? Because tfunc *is* a template function, so it would technically be expanded at the time it was called, and at that time the compiler would know abou the func(int) function.

Also, in VC 7.1’s defence it does state that it is 98 or 97% standards compliant or something, it doesnt state that it is 100% standards compliant.

Has anyone used the vc express products? Or does anyone have any idea about the level of standard compliancy in it?

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Sep 09, 2005 at 13:54

@bladder

Wrong again, func(int) wasn’t defined until after the definition of tfunc. Therefore, it shouldn’t be considered in the list of possible overloads to call when tfunc calls func. func(char) should be called twice.

intresting, I didn’t know this one. Are you sure this is supposed to happen? Because tfunc *is* a template function, so it would technically be expanded at the time it was called, and at that time the compiler would know abou the func(int) function.

It is actually in the MSDN documentation that VC++ doesn’t behave according to the standard in that retrospect. Not that the docs point to paragraph 14.6.2 (dependent names) in the standard, while they in fact mean paragraph 14.6.3 (non-dependent names):

14.6.3 - Non-dependent names [temp.nondep]

-1- Non-dependent names used in a template definition are found using the usual name lookup and bound at the point they are used. [Example:

void g(double);
void h();

template<class T> class Z {
public:
    void f() {
  g(1);           //  calls  g(double)
  h++;            //  ill-formed: cannot increment function;
    //  this could be diagnosed either here or
    //  at the point of instantiation
    }
};

void g(int);                    //  not in scope at the point of the template
    //  definition, not considered for the call  g(1)

It’s a bit weird though, this also means that a function like std::swap, which by default uses the assignment operator and a local temporary to make the swap for a custom type, shouldn’t work for that type if it’s not defined until after the definition of std::swap itself. But it works nevertheless. Comeau also reports the following:

template<class T> void tfunc(T t)
{
    func(t);
}

void func(int);

struct S { };
void func(S);

int main()
{
    int i = 4;
    S s;

    tfunc(i); // error: func(int) not declared at definition of tfunc
    tfunc(s); // this is fine
}

So for some reason, this rule only applies to primitive types. Well, I can guess the reason, if it also applies to user types template functions would be pretty useless, but why a different approach for primitives?

Also, in VC 7.1’s defence it does state that it is 98 or 97% standards compliant or something, it doesnt state that it is 100% standards compliant.

Sure, and I think VC++ is a great compiler (since 7.1), I use it both for work (ok, not much choice there :wink:) and hobby. But saying comeau isn’t any more compliant than VC++ is just a stab in the face of comeau :)

Has anyone used the vc express products? Or does anyone have any idea about the level of standard compliancy in it? [snapback]21039[/snapback]

I tried VC++ 2005 express beta, hasn’t changed a bit with regards to compliance. I do love C++/cli though, and that’ll be my first entry point into .Net :)

46407cc1bdfbd2db4f6e8876d74f990a
0
Kenneth_Gorking 101 Sep 10, 2005 at 16:58

.oisyn, you are assuming that the Microsoft compiler behaves according to the standards when it is compiling template classes/functions, which it doesn’t. Hell, it doesn’t even check the tempate classes/functions until they are used. A simple test:

template<class T> class TError
{
public:
    TError()
    {
  I Am an error
    }
};

This will compile just fine under VC7.1.

You may know your standards, but you don’t know your compiler.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Sep 13, 2005 at 07:32

you are assuming that the Microsoft compiler behaves according to the standards when it is compiling template classes/functions, which it doesn’t

Pardon me? I suggest you reread my post. I was talking about Comeau, and if you have read this thread thouroughly you’d know that I would never assume such a thing about the MSVC++ compiler ;)