Re: [boost] VC8 type traits documentation

-----Original Message----- From: narechk [mailto:narechk@gmail.com] Sent: Wednesday, July 13, 2005 10:29 AM Subject: Re: VC8 type traits documentation
It appears the support for compiler intrinsic type traits in Beta2 is implemented only partially:
typedef int T; __is_pod(T); __has_trivial_constructor(T); __has_trivial_copy(T); __has_trivial_assign(T); __has_trivial_destructor(T); __has_nothrow_constructor(T); __has_nothrow_copy(T); __has_nothrow_assign(T);
Ditto for the rest of fundamental types. All of the above return false, which AFAIK is incorrect! [§3.9, ¶10; §9, ¶4]
The compiler intrinsics are only there to provide the type information that is otherwise unavailable. Put another way, for fundamental types, we decided we don't care what the value is (we default to false) since an implementation of type traits can get the right value. This simplifies the implementation and puts the burden on the library implementation which can change more easily than the compiler.
struct A { A() {} A(const A&) {} const A& operator=(const A&) {} };
typedef A T; __is_pod(T); // false __has_trivial_constructor(T); // false __has_trivial_copy(T); // false __has_trivial_assign(T); // false __has_trivial_destructor(T); // true __has_nothrow_constructor(T); // false, too conservative __has_nothrow_copy(T); // false, too conservative __has_nothrow_assign(T); // false, too conservative
The compiler is too conservative regarding nothrow, it should be able to deduce that constructor, copy and assign can never throw.
struct B { B() throw() {} B(const B&) throw() {} const B& operator=(const B&) throw() {} };
typedef B T; __is_pod(T); // false __has_trivial_constructor(T); // false __has_trivial_copy(T); // false __has_trivial_assign(T); // false __has_trivial_destructor(T); // true __has_nothrow_constructor(T); // true __has_nothrow_copy(T); // true __has_nothrow_assign(T); // true
It seems the compiler needs an explicit nothrow statement in order for ctor, copy and assign to be qualified as nothrow. Presumably the result of nothrow deduction is not fed to the intrinsics correctly in this version.
Can someone comment on the above.
You are correct that the compiler _could_ deduce nothrow in your example, but in general the compiler couldn't (for example, if the definition of the function is in the current translation unit), and therefore shouldn't try. -- Jason Shirk VC++ Compiler Team

Jason, thank you for shedding some light on this issue. [snip]
The compiler intrinsics are only there to provide the type information that is otherwise unavailable. Put another way, for fundamental types, we decided we
don't care what the
value is (we default to false) since an implementation of type traits can get the right value.
This simplifies the implementation and puts the burden on the library implementation which can change more easily than the compiler.
I see your point. It seems the library (dinkumware) which ships with Beta2 does not contain type traits for fundamental types from which one can extract the correct values for __is_xxx or __has_xxx intrinsics. Is this going to change in the final release of VC8 or is there another way of getting the correct TT values for undamental types (besides doing it yourself)?
struct A { A() {} A(const A&) {} const A& operator=(const A&) {} };
typedef A T; __is_pod(T); // false __has_trivial_constructor(T); // false __has_trivial_copy(T); // false __has_trivial_assign(T); // false __has_trivial_destructor(T); // true __has_nothrow_constructor(T); // false, too conservative __has_nothrow_copy(T); // false, too conservative __has_nothrow_assign(T); // false, too conservative
The compiler is too conservative regarding nothrow, it should be able to deduce that constructor, copy and assign can never throw.
struct B { B() throw() {} B(const B&) throw() {} const B& operator=(const B&) throw() {} };
typedef B T; __is_pod(T); // false __has_trivial_constructor(T); // false __has_trivial_copy(T); // false __has_trivial_assign(T); // false __has_trivial_destructor(T); // true __has_nothrow_constructor(T); // true __has_nothrow_copy(T); // true __has_nothrow_assign(T); // true
It seems the compiler needs an explicit nothrow statement in order for ctor, copy and assign to be qualified as nothrow. Presumably the result of nothrow deduction is not fed to the intrinsics correctly in this version.
Can someone comment on the above.
You are correct that the compiler _could_ deduce nothrow in your example, but in general the compiler couldn't (for example, if the definition
function is in the current translation unit), and therefore shouldn't
of the try.
I was under the impression that the compiler always performs an attempt to determine whether a type (including function types) is nothrow, for all types in a translation unit. If it didn't, it would have to conservatively assume that any function not declared as an explicit nothrow may throw an exception, forcing the compiler to enclose each and every non-nothrow function in implicit try/catch blocks along the entire call chain (or at least those requiring unwinding); looking at assembler output for an arbitrary program shows this is not the case. If I understand correctly the use of try/catch blocks disables certain optimizations (such as ie inlining etc) which is not good for performance. My concern is that for types such as this: template <typename Type> struct X { Type val; X() {} X(const Type& in): val(in) {} }; it is impossible to qualify the ctor and copy as an explicit nothrow because one can not know with which Type the template is specialized (eg Type can be a fundamental type, or a UDT with ctor/copy which may throw). However the compiler has that information at compile-time during specialization of X with Type. It would be a tremendous benefit for a library to have such information being exposed through __has_nothrow_xxx intrinsics because they would provide optimization opportunities with many uses, for example array construction / uninitialized copy with rollback semantics. Thanks, - NK

I see your point. It seems the library (dinkumware) which ships with Beta2 does not contain type traits for fundamental types from which one can extract the correct values for __is_xxx or __has_xxx intrinsics. Is this going to change in the final release of VC8 or is there another way of getting the correct TT values for undamental types (besides doing it yourself)?
Or by using Boost.Type Traits you'll get support for both fundamental types, and for types that are supported by the new compiler intrinsics. John.
participants (3)
-
Jason Shirk
-
John Maddock
-
Narech Koumar