Opened 15 years ago

Closed 15 years ago

#1828 closed Bugs (fixed)

is_class maybe triggering a VC8 compiler bug

Reported by: Stefan Owned by: John Maddock
Milestone: Boost 1.36.0 Component: type_traits
Version: Boost 1.34.1 Severity: Problem
Keywords: Cc:

Description

The following code compiles with an error. However there shouldn't be an error. Basically, the line in main() fails to compile because the compiler thinks sizeof(&Der::foo) is 16, which just can't be so. This case is very intricate, and any modifications to the code compile cleanly. For example, if instead of is_class, we use is_void, the code compiles; if hasher is not partially specialized for pointers, it compiles; if 'base' doesn't use CRTP, it compiles; if hasher<T> isn't a member variable, it compiles; if hasher is parametrized by T* or something else, it compiles.

#include <boost/type_traits/is_class.hpp> template <class T> struct hasher {}; template <class T> struct hasher<T*>

: boost::is_class<T>

{}; template <class T> struct hash_set {

hasher<T> hash;

}; template <class D> struct base {

hash_set<D*> set;

}; struct Der

: public base<Der>

{

void foo();

}; int main() {

char x[sizeof(&Der::foo) == 16 ? -1 : 1];

}

I don't think this is a boost bug - the failing conditions look too much like a compiler-specific bug. Also, this code compiles cleanly on gcc 3.4.2

I'd like to hear your opinion, and forward the bug to Microsoft if it's really their bug.

Change History (3)

comment:1 by anonymous, 15 years ago

Update: the following simple code produces the same bug on VC8.

It seems that using this form of SFINAE on an incomplete type makes the compiler remember an inappropriate size for member function pointers. Methinks that implementing is_class in terms of the intrinsic is_class would solve this problem.

#include <boost/type_traits/is_class.hpp> struct base; boost::is_class<base> stub; struct base {

void foo();

}; int main() {

char x[sizeof(&base::foo) == 16 ? -1 : 1];

}

comment:2 by John Maddock, 15 years ago

That's strange: builds OK for me with VC8 (and SVN Trunk), what am I missing?

Ah... now I see... is_class in trunk has been changed to use the is_class intrinsic. The code fails as you mention with 1.35.0.

But... why can't a pointer to member be 16-bytes? If instead of your assert I add:

std::cout << sizeof(&Der::foo) << std::endl; void (Der::*mp)(); std::cout << sizeof(mp) << std::endl;

Then both output 16 - really though this should be reserved for pointers to (possibly) virtual functions - I'm not sure why the compiler thinks that might be the case here though... I don't think there's anything in is_class that would trigger that, and is_polymorphic answers false for that type so that's all right. Why does it matter what size the member function pointer is?

Ah.. just got your update when trying to post, SVN Trunk already uses is_class, does this fix things for you?

John.

comment:3 by John Maddock, 15 years ago

Resolution: fixed
Status: newclosed

I'm assuming that this is fixed in Trunk, please reopen if problems re-occur.

Note: See TracTickets for help on using tickets.