vc >> Compiler template bug in VC++ 7.1 with pointer to members

by Gianni Mariani » Sun, 14 Dec 2003 16:22:52 GMT


I believe the code below is compliant with the C++ standard. GCC and
Comeau compiles this code without complaint however VC++ 7.1 has a
number of silly complaints.

Are there any known work arounds ?

template <typename T>
class foo
{
public:
typedef typename T::foo_inner foo_inner;

void func(
foo_inner * foo_inner::* member
)
{
}

void func2(
typename T::foo_inner * T::foo_inner::* member
)
{
}
};

VC++ 7.1 generates the following errors.

test.cpp(11) : error C2653: 'foo<T>::foo_inner' : is not a class or
namespace name

test.cpp(7) : see declaration of 'foo<T>::foo_inner'

test.cpp(20) : see reference to class template instantiation 'foo<T>'
being compiled

test.cpp(17) : error C2653: 'foo_inner' : is not a class or namespace name





vc >> Compiler template bug in VC++ 7.1 with pointer to members

by David Lowndes » Sun, 14 Dec 2003 22:15:14 GMT


>I believe the code below is compliant with the C++ standard. GCC and

Gianni,

The latest Whidbey alpha compiler also exhibits the same errors, so
I'll try to pass them your report on to MS.


I'm afraid I don't know.

Dave
--
MVP VC++ FAQ: http://www.mvps.org/vcfaq

vc >> Compiler template bug in VC++ 7.1 with pointer to members

by William M. Miller » Mon, 15 Dec 2003 22:59:28 GMT


It appears that VC++ does a "trial instantiation" with an
invented type in order to parse the template, and they didn't
set up the nested "foo_inner" with the appropriate attributes
to be used as a nested-name-specifier in a qualified-id (or
they didn't suppress this particular error message -- I don't
know the internals of the compiler so I can't say for sure
which technique they used).

As for a workaround, you could do something like this:

struct local_foo: T::foo_inner { };
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^
^^^^^^^^^

Ugly, but it should work okay.

-- William M. Miller

vc >> Compiler template bug in VC++ 7.1 with pointer to members

by Gianni Mariani » Wed, 17 Dec 2003 15:14:56 GMT


...

I'm not sure.. I think there would be a member pointer conversion error.


struct A
{
int a;
};

struct B : A
{
int b;
};


typedef int A::* A_mptr;
typedef int B::* B_mptr;

A_mptr aptr1 = &B::a; // this seems ok (I'm not sure why)

B_mptr bptr1 = &B::a;

int main()
{
aptr1 = bptr1; // error ...
}


I did come up with a different work-around, I typedef'd the member to
pointer type in the class being passed into the template. So there was
no ptr to member parsing in the template.

vc >> Compiler template bug in VC++ 7.1 with pointer to members

by William M. Miller » Wed, 17 Dec 2003 21:43:55 GMT


No. See below.


The reason this is okay is that the type of "&B::a" is
"int A::*" -- it reflects the class in which the member
is declared, not the class used to name the member. If
you had said "&B::b", it would have been an error. See
below.


Yes, that's an error, but that's not what I was doing above.
Remember, class type conversions and pointer-to-member
conversions are type-safe in opposite directions. You can
safely convert a pointer-to-derived into a pointer-to-base
because a derived object "is-a" base object -- or, equivalently,
because a derived object is guaranteed to have a base-class
subobject. You can safely convert a pointer-to-base-member
into a pointer-to-derived-member because it's guaranteed that
the derived class will have every member that the
pointer-to-base-member might be pointing to, while the inverse
is not necessarily true.

In my suggested workaround, calling foo<T>::func would involve
converting the argument from a T::foo_inner::* (i.e., a
pointer-to-base-member) to a foo<T>::local_foo::* (i.e., a
pointer-to-derived-member), which is the permitted direction.
Your example of "aptr1 = bptr1" attempts to convert in the
opposite direction, which is an error.


That's fine, too, if you control the declarations of the classes
with which the template will be instantiated.

-- William M. Miller

Similar Threads

1. a possible performance bug in VC 7.1 compiler

To Carl (or other folks from MSFT):

When compiling LAPACK (a numerical library) on VC 7.1 I 
encountered a file that took forever to compile under the 
Release mode. The file has under 2,000 lines and it takes 
over 8 minutes to compile that file alone on my super new 
dual Xeon 4GB RAM machine. Each of the other files in this 
library takes under a second to compile and some of them 
are much larger.

I realize that it is the content of the source file that 
mostly influences the time needed for compilation. Still, 
it seems to me that something is not right. 

If you have LAPACK library, the name of the file is 
clarfx.c. If you don't I will be happy to email it to you.

Bumbrlik

2. vc 7.1 compiler bug

3. VC++ 7.1 compiler bug with default parameters

This bug is easier to just show than to explain I think...

namespace M {
    template <class T> struct A {
        void f(int a = T::foo()) { } // line 5
    };
}

namespace N {
    struct B {
        static int foo() { return 5; }
    };
}

int main() {
    M::A<N::B> x;
    x.f();
}

VC++ 7.1 (13.10.3077) produces the following diagnostic:
test.cpp(5) : error C2653: 'B' : is not a class or namespace name
test.cpp(5) : error C3861: 'foo': identifier not found, even with
argument-dependent lookup

Taking B out of namespace N makes it work, as does eliminating the
default parameter and providing an overload of A::f with no parameters
(which can serve a general workaround -- although it would be annoying
for constructors).

Both gcc 3.2 and Comeau 4.3.1 compile this code with no problem.

John

4. VC++ 7.1 (.net 2003) compiler code optimization bug ?

5. VC++ 7.1 compiler BUG

6. Nested enums and default member initialization(possible bug in VC 7.1)

7. Template instantiation problem with vc++.net 7.1 compiler

Guys please help me to solve this strange problem what Iam 
getting as follows..

Trying to instantiate a global instance of a template 
class as follows :-

when i build this code with debug and run this works fine. 
but if build in unicode release or release this does't 
work.
IS THERE ANY PROBLEM OF INSTANTIATING TEMPLATE CLASSES 
GLOBALY IN APPLICATION BUILD WITH UNICODE RELEASE OR 
RELEASE ??????
( this is only happening with visual studio .net compiler 
version 7.1. I have tried with vc++ 6.0 this works fine)

class a
{
public:
    a() {}
};
// specialize constructor with a dummy class
class dummy
{
};
template <class T> class tc
{
public:
    tc(const dummy&)
    {
         MessageBox(NULL, _T("template with dummy Got 
constructed..."), _T(""), MB_OK);
    }
private:
    const static tc<T>* ptc; // Initialize when this 
classs constructs
};
// construct a global templete object here
const tc<a>* tc<a>::ptc = new tc<a>(dummy());
int main(int argc, char* argv[])
{
	return 0;
}

Thanks in advance guys
Hari

8. VC 7.1 Bug related to templates ?!