RE: fallback support for traits
We currently have the _RWSTD_TT_* macros (referred to below as _TT_ macros). The original intent was to define them to the compiler built-in for the named type trait. I.e., _RWSTD_TT_IS_POD(T) would expand to __is_pod(T) on those systems that supply the __is_pod() built-in. While porting the traits, I wrote code to augment the definition of several of these macros. For instance, on eccp-3.10, the __has_trivial_constructor() built-in evaluates to false for scalar types and arrays of such types, but it does correctly detect class types that have a trivial default constructor. So I do something like this for such a platform... template struct __has_trivial_ctor_impl { typedef typename __rw_remove_all_extents<_TypeT>::type _TypeU; enum { value =__rw_is_scalar<_TypeU>::value || _RWSTD_TT_HAS_TRIVIAL_CTOR(_TypeU) }; }; #undef _RWSTD_TT_HAS_TRIVIAL_CTOR #define _RWSTD_TT_HAS_TRIVIAL_CTOR(T) \ _RW::__rw_has_trivial_ctor_impl::value Now I have a macro that evaluates to true under the right conditions, but it isn't defined to be the same as one of the built-ins as originally intended. It was suggested that I not do this, and instead only define the macros to the built-ins that are provided. The problem is that I don't really see the macros as being very useful when they are not as accurate as they could be. Another issue is that in some cases, my fallback (which uses little or no compiler support) is more accurate than the provided trait. In these cases, I don't define the _TT_ macro, and I just use the fallback implementation. So now I'm ignoring the compiler support in some cases. The advantage of doing this is that I don't need to add a bunch of conditional code to the internal headers to avoid using broken built-ins. So, my question is, what is the right way? Should I always define the _TT_ macros to the native traits only, even if they're broken and then just work around the issues at the definition of the trait template? Is it acceptable to not define the _TT_ macro when the internal trait is available, but is broken? Travis
Re: fallback support for traits
Travis Vitek wrote: Martin Sebor wrote: Travis Vitek wrote: I've already implemented fallback support for many traits. Here is a list of those that I can think of off of the top of my head... __rw_is_class __rw_is_union __rw_is_empty __rw_is_polymorphic __rw_is_abstract __rw_is_convertible __rw_is_base_of __rw_has_trivial_ctor __rw_has_trivial_copy __rw_has_trivial_assign __rw_has_trivial_dtor __rw_has_nothrow_ctor __rw_has_nothrow_copy __rw_has_nothrow_assign All of the fallbacks are supposed to provide a correct result where possible, otherwise they should return a pessimistic result. I.e. The fallback __rw_has_trivial_ctor::value will be true for all (possibly cv-qualified) scalar types, but will evaluate to false for class types (struct, union or class). Now I have to figure out what to do for a few more traits. Specifically __rw_alignment_of<> and __rw_aligned_storage<>. As it stands now, these traits require definition of _RWSTD_TT_ALIGN_OF() and _RWSTD_TT_ALIGNED_POD() to be defined. If the macros are not provided, we will see a compile failure. But only for the unusual specializations where the alignment isn't the same as one of the fundamental types, right? I can't see how to implement aligned_storage even for alignments that are equal to the alignments of fundamental types if I have no way to get the alignment a a fundamental type as an integral constant value. Isn't sizeof(T) a good enough guess? I mean, do we know of a platform where sizeof(T) isn't the same as the alignment of T for all fundamental types? As I see it, my options are... 1. put code that will prevent instantiation in the the type declaration (i.e. static_assert) 2. provide a suitable default that is not correct, but can be used to detect the failure 3. disable traits entirely by defining _RWSTD_NO_EXT_CXX_0X if the macros have not been defined 4. disable the affected traits (and their tests) if the macros have not been defined As I see it, option 4 is probably best. Especially given the recent discussion of removing all three alignment traits in favor of the new alignof and alignas keywords and non-trivial unions. We still need to write up the issue... Yeah. As for providing the traits only conditionally, I'm not sure that's the best approach. If we feel it likely that some of them will end up getting yanked from the working paper we should probably avoid providing them at all, otherwise we might be stuck maintaining them for a long time. Providing them only for some platforms would also make them difficult to use portably (we'd have to expose some kind of config macro for users to check whether the trait is defined or not). Why would we need to support them? If we disabled them by default and told users the functionality is experimental and depends on the direction of the standard, then it seems that we should be free to yank them. Of course that requires that the functionality be disabled by default (which we're currently talking about changing). That's one way to interpret it. I guess I never thought of it as including the removal of new features, only (hopefully fairly small) changes. So my preference would be either (2) or (5), with option 5 being to disable the aligned traits unconditionally until we know for certain that they aren't going away. I would be okay with that also. Okay, then I suggest we go with the more conservative one of the two (i.e., 5). That way we don't have to worry about removing features after they've been released and potentially used by customers. You can leave the code in place but #ifdef it out by some internal macro. If you want to continue to test the traits so they don't get broken by something, have the tests #define the macro before including . Out of curiosity, what do other implementations do? Ah, here is the answer. I had written code to try to detect alignment, and it worked on msvc-7.1 and msvc-8.0, but failed to compile on gcc-4.3 and eccp-3.10. As it turns out the Boost library is using a very similar trick that appears to work on both compilers. So this gets me an implementation of __rw_alignment_of<>. With that I should be able to provide a fallback implementation of __rw_aligned_storage<> that works with fundamental alignments. Thank you for nudging me to look back at the reference implementation. Travis Martin Input anyone? Travis
RE: fallback support for traits
Martin Sebor wrote: > >Travis Vitek wrote: >> I've already implemented fallback support for many traits. Here is a >> list of those that I can think of off of the top of my head... >> >> __rw_is_class >> __rw_is_union >> __rw_is_empty >> __rw_is_polymorphic >> __rw_is_abstract >> __rw_is_convertible >> __rw_is_base_of >> __rw_has_trivial_ctor >> __rw_has_trivial_copy >> __rw_has_trivial_assign >> __rw_has_trivial_dtor >> __rw_has_nothrow_ctor >> __rw_has_nothrow_copy >> __rw_has_nothrow_assign >> >> All of the fallbacks are supposed to provide a correct result where >> possible, otherwise they should return a pessimistic result. I.e. The >> fallback __rw_has_trivial_ctor::value will be true for >> all (possibly cv-qualified) scalar types, but will evaluate to false >> for class types (struct, union or class). >> >> Now I have to figure out what to do for a few more traits. >> Specifically __rw_alignment_of<> and __rw_aligned_storage<>. As it >> stands now, these traits require definition of _RWSTD_TT_ALIGN_OF() >> and _RWSTD_TT_ALIGNED_POD() to be defined. If the macros are not >> provided, we will see a compile failure. > >But only for the unusual specializations where the alignment >isn't the same as one of the fundamental types, right? I can't see how to implement aligned_storage even for alignments that are equal to the alignments of fundamental types if I have no way to get the alignment a a fundamental type as an integral constant value. > >> >> As I see it, my options are... >> >> 1. put code that will prevent instantiation in the the type >> declaration (i.e. static_assert) >> 2. provide a suitable default that is not correct, but can be >> used to detect the failure >> 3. disable traits entirely by defining _RWSTD_NO_EXT_CXX_0X if >> the macros have not been defined >> 4. disable the affected traits (and their tests) if the macros >> have not been defined >> >> As I see it, option 4 is probably best. Especially given the recent >> discussion of removing all three alignment traits in favor of the new >> alignof and alignas keywords and non-trivial unions. > >We still need to write up the issue... Yeah. >As for providing the traits only conditionally, I'm not sure >that's the best approach. If we feel it likely that some of >them will end up getting yanked from the working paper we >should probably avoid providing them at all, otherwise we >might be stuck maintaining them for a long time. Providing >them only for some platforms would also make them difficult >to use portably (we'd have to expose some kind of config >macro for users to check whether the trait is defined or >not). Why would we need to support them? If we disabled them by default and told users the functionality is experimental and depends on the direction of the standard, then it seems that we should be free to yank them. Of course that requires that the functionality be disabled by default (which we're currently talking about changing). > >So my preference would be either (2) or (5), with option 5 >being to disable the aligned traits unconditionally until >we know for certain that they aren't going away. I would be okay with that also. > >Out of curiosity, what do other implementations do? Ah, here is the answer. I had written code to try to detect alignment, and it worked on msvc-7.1 and msvc-8.0, but failed to compile on gcc-4.3 and eccp-3.10. As it turns out the Boost library is using a very similar trick that appears to work on both compilers. So this gets me an implementation of __rw_alignment_of<>. With that I should be able to provide a fallback implementation of __rw_aligned_storage<> that works with fundamental alignments. Thank you for nudging me to look back at the reference implementation. Travis > >Martin > >> >> Input anyone? >> >> Travis > >
RE: fallback support for traits
Travis Vitek wrote: > > >As I see it, my options are... > > 1. put code that will prevent instantiation in the the type >declaration (i.e. static_assert) > 2. provide a suitable default that is not correct, but can be >used to detect the failure > 3. disable traits entirely by defining _RWSTD_NO_EXT_CXX_0X if >the macros have not been defined > 4. disable the affected traits (and their tests) if the macros >have not been defined > Another option would be to write config tests to look for __alignof() and alignof(). If these are found, then we could use them. If not we could get the alignment of a few primitive types, and I could provide an aligned_storage implementation that supports only these alignments. The test would need to check a bunch of macros, but it would all work out.
Re: fallback support for traits
Travis Vitek wrote: I've already implemented fallback support for many traits. Here is a list of those that I can think of off of the top of my head... __rw_is_class __rw_is_union __rw_is_empty __rw_is_polymorphic __rw_is_abstract __rw_is_convertible __rw_is_base_of __rw_has_trivial_ctor __rw_has_trivial_copy __rw_has_trivial_assign __rw_has_trivial_dtor __rw_has_nothrow_ctor __rw_has_nothrow_copy __rw_has_nothrow_assign All of the fallbacks are supposed to provide a correct result where possible, otherwise they should return a pessimistic result. I.e. The fallback __rw_has_trivial_ctor::value will be true for all (possibly cv-qualified) scalar types, but will evaluate to false for class types (struct, union or class). Now I have to figure out what to do for a few more traits. Specifically __rw_alignment_of<> and __rw_aligned_storage<>. As it stands now, these traits require definition of _RWSTD_TT_ALIGN_OF() and _RWSTD_TT_ALIGNED_POD() to be defined. If the macros are not provided, we will see a compile failure. But only for the unusual specializations where the alignment isn't the same as one of the fundamental types, right? As I see it, my options are... 1. put code that will prevent instantiation in the the type declaration (i.e. static_assert) 2. provide a suitable default that is not correct, but can be used to detect the failure 3. disable traits entirely by defining _RWSTD_NO_EXT_CXX_0X if the macros have not been defined 4. disable the affected traits (and their tests) if the macros have not been defined As I see it, option 4 is probably best. Especially given the recent discussion of removing all three alignment traits in favor of the new alignof and alignas keywords and non-trivial unions. We still need to write up the issue... As for providing the traits only conditionally, I'm not sure that's the best approach. If we feel it likely that some of them will end up getting yanked from the working paper we should probably avoid providing them at all, otherwise we might be stuck maintaining them for a long time. Providing them only for some platforms would also make them difficult to use portably (we'd have to expose some kind of config macro for users to check whether the trait is defined or not). So my preference would be either (2) or (5), with option 5 being to disable the aligned traits unconditionally until we know for certain that they aren't going away. Out of curiosity, what do other implementations do? Martin Input anyone? Travis
fallback support for traits
I've already implemented fallback support for many traits. Here is a list of those that I can think of off of the top of my head... __rw_is_class __rw_is_union __rw_is_empty __rw_is_polymorphic __rw_is_abstract __rw_is_convertible __rw_is_base_of __rw_has_trivial_ctor __rw_has_trivial_copy __rw_has_trivial_assign __rw_has_trivial_dtor __rw_has_nothrow_ctor __rw_has_nothrow_copy __rw_has_nothrow_assign All of the fallbacks are supposed to provide a correct result where possible, otherwise they should return a pessimistic result. I.e. The fallback __rw_has_trivial_ctor::value will be true for all (possibly cv-qualified) scalar types, but will evaluate to false for class types (struct, union or class). Now I have to figure out what to do for a few more traits. Specifically __rw_alignment_of<> and __rw_aligned_storage<>. As it stands now, these traits require definition of _RWSTD_TT_ALIGN_OF() and _RWSTD_TT_ALIGNED_POD() to be defined. If the macros are not provided, we will see a compile failure. As I see it, my options are... 1. put code that will prevent instantiation in the the type declaration (i.e. static_assert) 2. provide a suitable default that is not correct, but can be used to detect the failure 3. disable traits entirely by defining _RWSTD_NO_EXT_CXX_0X if the macros have not been defined 4. disable the affected traits (and their tests) if the macros have not been defined As I see it, option 4 is probably best. Especially given the recent discussion of removing all three alignment traits in favor of the new alignof and alignas keywords and non-trivial unions. Input anyone? Travis