Re: rw/_defs.h included last?
Travis Vitek wrote: Martin Sebor wrote: [...] In all library headers: 1. standard headers (C++, including stdcxx own, C, or POSIX are never included (there are a shrinking number of exceptions to this rule) So, as an example, if one of us needed to use std::integral_constantT,V in some header, the definition of that type would need to be moved to some private header and included from both places to avoid including type_traits. I can buy this as it fits with the unnecessary namespace polution problem that keeps coming up. Right. Although it should be balanced against the cost of #including a whole header for just a single definition. That's why we have headers such as rw/_algobase.h or rw/_iterbase.h: to group the most commonly needed sets of definitions and not a separate header for each of the definitions in these headers. 2. include directives are in alphabetical order, with rw/_defs.h being last (it still ends up getting included first, indirectly, by the first header); the exception here is when a stdcxx config macro needs to be tested before the first #include directive Okay, and what is the rationale for including rw/_defs.h last? If it provides defines that are needed by the current file, why not just put it in the list in alphabetical order like the others? It used to be first. IIRC, the idea behind including it last was to make it more likely for things to break if the #include directive was missing. I'm not sure how well well thought out it was. If it's causing trouble and going back to how it used to be way back when makes more sense (i.e., eliminates the exceptional case) I have no problem with it. 3. each #include directive in every standard header is guarded with a preprocessor conditional testing the XXX_INCLUDED macro for the corresponding header for compile-time efficiency I'm assuming that you're talking about this kind of thing... #ifndef _RWSTD_RW_ALGOBASE_H_INCLUDED # include rw/_algobase.h #endif // _RWSTD_RW_ALGOBASE_H_INCLUDED #ifndef _RWSTD_RW_ITERBASE_H_INCLUDED # include rw/_iterbase.h #endif // _RWSTD_RW_ITERBASE_H_INCLUDED I looked in a handful of standard headers and didn't see this model anywhere. I do see it in many of the private headers, but it is not being used consistently. I thought I had implemented it this way but it looks like I misremembered. Do we have any evidence that shows this 'optimization' is actually improving compile times? I haven't done any benchmarking with stdcxx but what's in stdcxx now was done based on a user request: http://issues.apache.org/jira/browse/STDCXX-213 Other than that, as I already said in another thread, there is plenty of evidence out there that #include directives can have a dramatic impact on compile times. That's why many modern compilers provide this optimization either via special purpose mechanisms like #pragma once or even automatically. In library sources: 1. sets of C++, C, POSIX, and stdcxx-private headers are included in separate blocks of their own, in alphabetical order within each block 2. C headers are included using the xxx.h form (as opposed to the cxxx form) for better portability Martin
Re: tests/utilities/20.meta.help.cpp
Travis Vitek wrote: Eric Lemings wrote: Just a brief side note. I was just reviewing this test and noticed that pointers are not tested though they are valid scalar types suitable for use as integral_constant parameters. I think references may be valid parameters also. I'm not sure. The first thing that jumps to mind is that a pointer is not of 'integral' type. An enumeration isn't really an integral type either, but they are implicitly convertible to one. Pointers aren't convertible to integral type without a cast. According to temp.arg.nontype, a non-type, non-template template parameter must be one of -- an integral constant expression -- the name of a non-type template-parameter -- the address of an object or function with external linkage... -- a constant expression that evaluates to a null pointer value -- a constant expression that evaluates to a null member pointer value -- a pointer to member So, yes, it is legal to use a pointer as a non-type template parameter. The issue I have is that the integral_constantT,V is supposed to define an integral constant of type T with value V. Section expr.const says that a constant expression is an integral constant expression if it is of integral or enumeration type. An integral constant expression can be used as an array bound, a case expression, a bit field length, enumeration initializer, static member initializer and as integral or enumeration non-type template arguments. I'm pretty sure you can't use a pointer value as an array bound, case expression, bit field length or enumeration initializer, so they aren't really integral constants. So I am sure you can instantiate std::integral_constantvoid (class_t::*)(), class::method, but I'm not sure if it something that should be tested. If there's an implementation technique that would make the instantiation ill-formed then I think it should be tested. More important, though, the standard should specify the requirements on the template arguments. If there are no such requirements for something as fundamental as integral_const, either in the latest working draft or in one of the concepts papers (such as N2622), we should at least bring it up on the list and/or open an issue to have the spec clarified. Martin Brad.
Re: Inconsistent indentation in preprocessing directives
Eric Lemings wrote: I was just looking at the indentation in the $TOPDIR/include/rw/_static_assert.h header. Why are the defines within the `#ifndef _RWSTD_NO_STATIC_ASSERT' indented but the directives outside this #if/#else/#endif block are not? Should they all be indented uniformly or not indented at all? I agree it's inconsistent but I'm not sure there is much to be gained from indenting the body of the top level blocks. The purpose of the indentation is to aid readability and Since virtually every header is always enclosed in a pair of #ifdefs, indenting its contents wouldn't do anything to help in this regard. Martin I realize this is not conventional but if we want to indent preprocessing directives, this file should look like this: #ifndef _RWSTD_RW_STATIC_ASSERT_H_INCLUDED # define _RWSTD_RW_STATIC_ASSERT_H_INCLUDED # include rw/_defs.h ... # ifndef _RWSTD_NO_STATIC_ASSERT #define _RWSTD_STATIC_ASSERT(Cond) ... # else #define _RWSTD_STATIC_ASSERT(Cond,Mesg) static_assert(Cond, Mesg) # endif // _RWSTD_NO_STATIC_ASSERT #endif // _RWSTD_RW_STATIC_ASSERT_H_INCLUDED Otherwise, we shouldn't indent at all. Thanks, Brad.
Re: svn commit: r667636 - /stdcxx/branches/4.3.x/include/rw/_forward.h
Eric Lemings wrote: Gah. I have to update my docs as well: template parameters are documented using the @tparam tag rather than the @param tag. I thought we said we wouldn't be using doxygen comments in library code. Am I misremembering? Martin http://www.stack.nl/~dimitri/doxygen/commands.html#cmdtparam Brad. -Original Message- From: Travis Vitek Sent: Monday, June 16, 2008 11:47 AM To: Eric Lemings Subject: RE: svn commit: r667636 - /stdcxx/branches/4.3.x/include/rw/_forward.h Damn, now I have to update my dox. -Original Message- From: Eric Lemings Sent: Monday, June 16, 2008 10:44 AM To: Travis Vitek Subject: RE: svn commit: r667636 - /stdcxx/branches/4.3.x/include/rw/_forward.h -Original Message- From: Travis Vitek Sent: Monday, June 16, 2008 10:21 AM To: Eric Lemings Subject: RE: svn commit: r667636 - /stdcxx/branches/4.3.x/include/rw/_forward.h Author: elemings Date: Fri Jun 13 13:16:06 2008 New Revision: 667636 +/** + * An identity wrapper. Similar to the identity property, the identity + * wrapper is a class template that simply reflects the type of its + * template parameter. This class template is used when a template + * parameter type must be explicitly specified in order to apply the + * correct move/forwarding semantics, usually in the \c std::forward() + * function. + * + * @param _Type Any type. No restrictions or requirements. + * @see std::forward + */ +template class _Type +struct identity Does doxygen handle @param when we are talking about a template parameter? Not yet. http://www.mail-archive.com/[EMAIL PROTECTED] /msg163022.html
RE: svn commit: r667636 - /stdcxx/branches/4.3.x/include/rw/_forward.h
Martin Sebor wrote: Eric Lemings wrote: Gah. I have to update my docs as well: template parameters are documented using the @tparam tag rather than the @param tag. I thought we said we wouldn't be using doxygen comments in library code. Am I misremembering? I know that it was requested that I remove the doxygen comments from the type traits stuff I have been working on, but I decided it would be best to commit them with the comments intact and remove them only if necessary. I mentioned this to Brad in our off-list correspondence, and he has opted to do the same. As I sit here thinking about it, I can't remember exactly why it was decided that they should be removed. Perhaps it is best to have this discussion again, but on the list this time. To start, I'm not sure I understand the motivation for _not_ using doxygen in the library headers. I realize that having documentation in the code is a departure from what stdcxx has done in the past, but I'm not convinced that this is a bad thing. Travis Martin http://www.stack.nl/~dimitri/doxygen/commands.html#cmdtparam Brad.
Re: svn commit: r667365 [1/3] - in /stdcxx/branches/4.3.x: etc/config/src/ include/ include/rw/ tests/utilities/
Travis Vitek wrote: Martin Sebor wrote: Are you sure the traits are correct for char and wchar_t? No. Also, do you believe the working draft to be unambiguous and correct? No. For reference, I've pulled the requirements from the standard and pasted them below. There is at least one obvious ambiguity. Assume that char is signed. Should std::make_signedunsigned char::type be 'char' or 'signed char'? Yes. This needs to be clarified. Could you bring it up on [EMAIL PROTECTED] to make sure it's not a known problem that's already being handled? I'll help you write up the issue if it isn't. Same goes for std::make_signedenum_t::type when sizeof(enum_t) == sizeof(char). If both 'char' and 'signed char' are signed integral types, which of the two should be used? I didn't think enums could be smaller than int but that's probably going to change with scoped enums. It also seems wrong to have std::make_signedchar::type be 'signed char' only when 'char' is unsigned. It seems that users would like to be able to expect that the resulting type be consistent regardless of the signed-ness of char. Sounds like a valid point to me. OTOH, the actual type may not matter all that much just as long as the signedness is right. In my experience, in the handful of cases when I've ever needed an unsigned form of a (possibly) signed type all I cared about was the absence of signedness. Both of these issues make me think that the definition of make_signed should have said 'signed integer type' instead of 'signed integral type'. You mean just signed/unsigned integers (I had to look up the difference). I suspect most people would find a make_signed that didn't work with char to be broken. Based on my reading, make_signedT ::type should be the same as T if T is a signed integral type. IIUC, our make_signedchar::type is defined to signed char regardless of the signed-ness of char. Ditto for wchar_t. Right. That's what caught my attention because it goes against the requirement. Martin [basic.fundamental] p2 There are five standard signed integer types: signed char, short int, int, long int, and long long int. In this list, each type provides at least as much storage as those preceding it in the list. [...] The standard and extended signed integer types are collectively called signed integer types. [basic.fundamental] p3 For each of the standard signed integer types, there exists a corresponding standard unsigned integer type: unsigned char, unsigned short int, unsigned int, unsigned long int, and unsigned long long int, each of which occupies the same amount of storage and has the same alignment requirements as the corresponding signed integer type. [...] The standard and extended unsigned integer types are collectively called unsigned integer types. [basic.fundamental] p7 Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types. [meta.trans.sign] If T names a (possibly cv-qualified) signed integral type then the member typedef type shall name the type T; otherwise, if T names a (possibly cv-qualified) unsigned integral type then type shall name the corresponding signed integral type, with the same cv-qualifiers as T; otherwise, type shall name the signed integral type with smallest rank for which sizeof(T) == sizeof(type), with the same cv-qualifiers as T.
Re: svn propchange: r667365 - svn:log
[EMAIL PROTECTED] wrote: Author: vitek Revision: 667365 Modified property: svn:log Modified: svn:log at Mon Jun 16 09:47:35 2008 -- --- svn:log (original) +++ svn:log Mon Jun 16 09:47:35 2008 @@ -2,13 +2,32 @@ STDCXX-916 * include/type_traits: New file defines C++0x type traits. - * include/rw/_config-gcc.h: Add macros for compiler support. - * include/rw/_config-msvc.h: Ditto. + * include/rw/_config-gcc.h [_RWSTD_TT_IS_ENUM, _RWSTD_TT_IS_UNION, Not to be an overly pedantic PITA but my reading of the GNU coding standards is that the brackets are for conditionals, not for lists of added or changed names, so the names here should be in parentheses. Do you read it differently? Martin + _RWSTD_TT_IS_CLASS, _RWSTD_TT_IS_POD, _RWSTD_TT_IS_EMPTY, + _RWSTD_TT_IS_POLYMORPHIC, _RWSTD_TT_IS_ABSTRACT, _RWSTD_TT_IS_BASE_OF, + _RWSTD_TT_HAS_TRIVIAL_CTOR, _RWSTD_TT_HAS_TRIVIAL_COPY, + _RWSTD_TT_HAS_TRIVIAL_ASSIGN, _RWSTD_TT_HAS_TRIVIAL_DTOR, + _RWSTD_TT_HAS_NOTHROW_CTOR, _RWSTD_TT_HAS_NOTHROW_COPY, + _RWSTD_TT_HAS_TRIVIAL_ASSIGN, _RWSTD_TT_HAS_VIRTUAL_DTOR, + _RWSTD_TT_ALIGN_OF, _RWSTD_ALIGNED_POD, _RWSTD_MAX_ALIGNMENT]: Add + macros for compiler support. + * include/rw/_config-msvc.h [_RWSTD_TT_IS_ENUM, _RWSTD_TT_IS_UNION, + _RWSTD_TT_IS_CLASS, _RWSTD_TT_IS_POD, _RWSTD_TT_IS_EMPTY, + _RWSTD_TT_IS_POLYMORPHIC, _RWSTD_TT_IS_ABSTRACT, _RWSTD_TT_IS_BASE_OF, + _RWSTD_TT_IS_CONVERTIBLE, _RWSTD_TT_HAS_VIRTUAL_DTOR, + _RWSTD_TT_HAS_TRIVIAL_CTOR, _RWSTD_TT_HAS_TRIVIAL_ASSIGN, + _RWSTD_TT_HAS_TRIVIAL_COPY, _RWSTD_TT_HAS_TRIVIAL_DTOR, + _RWSTD_TT_HAS_NOTHROW_CTOR, _RWSTD_TT_HAS_NOTHROW_ASSIGN, + _RWSTD_TT_HAS_NOTHROW_COPY, _RWSTD_TT_ALIGN_OF, _RWSTD_TT_ALIGNED_POD, + _RWSTD_TT_MAX_ALIGNMENT]: Ditto. * include/rw/_config.h [_RWSTD_EXT_CXX_OX]: Disable C++0x extensions unless defined. * include/rw/_defs.h [_RWSTD_SWCHAR_INT_T]: Add new macro that defines a type that has same size and layout a the fictional signed wchar_t. + [_RWSTD_UWCHAR_INT_T]: Modify definition to handle case where + unsigned long is not the same size as unsigned int. Add case for + unsigned long long. * etc/config/src/STATIC_ASSERT.cpp: Add configuration test to check for C++0x static_assert. * include/rw/_static_assert.h [_RWSTD_STATIC_ASSERT]: Add a
Re: svn commit: r668340 - /stdcxx/branches/4.3.x/tests/utilities/20.meta.unary.prop.cpp
[EMAIL PROTECTED] wrote: Author: vitek Date: Mon Jun 16 16:07:26 2008 New Revision: 668340 URL: http://svn.apache.org/viewvc?rev=668340view=rev Log: 2008-06-16 Travis Vitek [EMAIL PROTECTED] STDCXX-920 * tests/utilities/20.meta.unary.prop.cpp: Use size_t instead of _RWSTD_SIZE_T. Update test to correctly reflect behaviors required by standard. Modified: stdcxx/branches/4.3.x/tests/utilities/20.meta.unary.prop.cpp Modified: stdcxx/branches/4.3.x/tests/utilities/20.meta.unary.prop.cpp URL: http://svn.apache.org/viewvc/stdcxx/branches/4.3.x/tests/utilities/20.meta.unary.prop.cpp?rev=668340r1=668339r2=668340view=diff == --- stdcxx/branches/4.3.x/tests/utilities/20.meta.unary.prop.cpp (original) +++ stdcxx/branches/4.3.x/tests/utilities/20.meta.unary.prop.cpp Mon Jun 16 16:07:26 2008 @@ -27,6 +27,8 @@ * **/ +#include stddef.h Any reason why this shouldn't be cstddef like in all other tests? Martin + #include rw_driver.h // compile out all test code if extensions disabled @@ -208,15 +210,15 @@ void test_trait (int line, const char* trait, const char* type, - _RWSTD_SIZE_T value, _RWSTD_SIZE_T expect) + size_t value, size_t expect) { rw_assert (value == expect, 0, line, %s%s::value is %zu, expected %zu, trait, type, value, expect); } -void test_trait (int line, _RWSTD_SIZE_T depth, - _RWSTD_SIZE_T value, _RWSTD_SIZE_T expect, +void test_trait (int line, size_t depth, + size_t value, size_t expect, const char* trait, const char* type) { rw_assert (value == expect, 0, line, @@ -374,9 +376,9 @@ static void test_is_trivial () { TEST (std::is_trivial, long, true); -TEST (std::is_trivial, C long, false); +TEST (std::is_trivial, C long, true); TEST (std::is_trivial, V long, true); -TEST (std::is_trivial, CV long, false); +TEST (std::is_trivial, CV long, true); TEST (std::is_trivial, long, false); TEST (std::is_trivial, C long, false); @@ -418,6 +420,7 @@ static void test_is_standard_layout () { TEST (std::is_standard_layout, long, true); +TEST (std::is_standard_layout, non_empty_t, true); // no non-static data members of non-standard-layout type TEST (std::is_standard_layout, member_taccess_controlled_t, false);
Re: svn commit: r669999 - /stdcxx/branches/4.3.x/include/rw/_meta_other.h
[EMAIL PROTECTED] wrote: Author: vitek Date: Fri Jun 20 10:27:42 2008 New Revision: 66 URL: http://svn.apache.org/viewvc?rev=66view=rev Log: 2008-06-20 Travis Vitek [EMAIL PROTECTED] STDCXX-926 * include/rw/_meta_other.h: Remove unnecessary whitespace, simplify workaround for msvc. Modified: stdcxx/branches/4.3.x/include/rw/_meta_other.h Modified: stdcxx/branches/4.3.x/include/rw/_meta_other.h URL: http://svn.apache.org/viewvc/stdcxx/branches/4.3.x/include/rw/_meta_other.h?rev=66r1=669998r2=66view=diff == --- stdcxx/branches/4.3.x/include/rw/_meta_other.h (original) +++ stdcxx/branches/4.3.x/include/rw/_meta_other.h Fri Jun 20 10:27:42 2008 @@ -266,31 +266,31 @@ struct __rw_biggest { typedef typename -__rw_conditional( sizeof _Type1 sizeof _Type2), +__rw_conditional(sizeof _Type1 sizeof _Type2), The type argument to sizeof needs to be enclosed in parens. If the code compiles as is we should report it as a bug to the compiler vendor. Martin
Re: svn commit: r667636 - /stdcxx/branches/4.3.x/include/rw/_forward.h
Eric Lemings wrote: -Original Message- From: Travis Vitek [mailto:[EMAIL PROTECTED] Sent: Monday, June 23, 2008 10:13 AM To: dev@stdcxx.apache.org Subject: RE: svn commit: r667636 - /stdcxx/branches/4.3.x/include/rw/_forward.h Martin Sebor wrote: Eric Lemings wrote: Gah. I have to update my docs as well: template parameters are documented using the @tparam tag rather than the @param tag. I thought we said we wouldn't be using doxygen comments in library code. Am I misremembering? I know that it was requested that I remove the doxygen comments from the type traits stuff I have been working on, but I decided it would be best to commit them with the comments intact and remove them only if necessary. I mentioned this to Brad in our off-list correspondence, and he has opted to do the same. As I sit here thinking about it, I can't remember exactly why it was decided that they should be removed. Perhaps it is best to have this discussion again, but on the list this time. To start, I'm not sure I understand the motivation for _not_ using doxygen in the library headers. I realize that having documentation in the code is a departure from what stdcxx has done in the past, but I'm not convinced that this is a bad thing. I'll add a couple points to that for the record. Much of this was precipitated when I noticed that GNU libstdc++ also includes their documentation right in the library headers and source code. Why? Because most, if not all, C/C++ preprocessors will strip comments by default during a first pass. Thus, the impact of extensive documentation comments on overall build times is negligible. Of course preprocessors strip comments. It's required by the language standards. But regardless of the translation stage at which the stripping takes place, it isn't without cost. I gave a number of arguments against Doxygen comments in stdcxx headers: 1) existing code doesn't use it and converting the raw HTML docs to Doxygen is an enormous task that none of us has the time to take on; Doxygenating new code without doing the same for the existing code is inconsistent and won't help us produce end-user documentation for the finished product 2) Doxygen markups are harder to read than ordinary comments (see 3), and in the library headers the volume of such comments will, in many cases, dwarf the amount of code 3) unless/until there is infrastructure to generate the HTML docs from the Doxygen comments documenting the library (or other parts of stdcxx) using Doxygen markups serves no purpose 4) the HTML generated from stdcxx headers is unavoidably ugly because of the necessity to uglify names (leading underscores, etc.) Martin
RE: svn commit: r667636 - /stdcxx/branches/4.3.x/include/rw/_forward.h
Martin Sebor wrote: Eric Lemings wrote: Travis Vitek wrote: Martin Sebor wrote: I thought we said we wouldn't be using doxygen comments in library code. Am I misremembering? I know that it was requested that I remove the doxygen comments from the type traits stuff I have been working on, but I decided it would be best to commit them with the comments intact and remove them only if necessary. I mentioned this to Brad in our off-list correspondence, and he has opted to do the same. As I sit here thinking about it, I can't remember exactly why it was decided that they should be removed. Perhaps it is best to have this discussion again, but on the list this time. To start, I'm not sure I understand the motivation for _not_ using doxygen in the library headers. I realize that having documentation in the code is a departure from what stdcxx has done in the past, but I'm not convinced that this is a bad thing. I'll add a couple points to that for the record. Much of this was precipitated when I noticed that GNU libstdc++ also includes their documentation right in the library headers and source code. Why? Because most, if not all, C/C++ preprocessors will strip comments by default during a first pass. Thus, the impact of extensive documentation comments on overall build times is negligible. Of course preprocessors strip comments. It's required by the language standards. But regardless of the translation stage at which the stripping takes place, it isn't without cost. I gave a number of arguments against Doxygen comments in stdcxx headers: 1) existing code doesn't use it and converting the raw HTML docs to Doxygen is an enormous task that none of us has the time to take on; Doxygenating new code without doing the same for the existing code is inconsistent and won't help us produce end-user documentation for the finished product Since we aren't providing any html documentation for any c++0x code at this time, maybe we should stop using html documentation? :P So the options are-- a) not document the c++0x code at all b) write up documentation for all new code in html to be consistent with what is used currently c) move all existing documentation over to doxygen before a single doxygen comment is added to the new code Another important point is that the stdcxx project doesn't have anyone volunteering time to write documentation. If we want the documentation, we're likely going to have to do it ourselves, and I find using doxygen comments _much_ simpler than writing html. I know that at Rogue Wave we have an xslt that transforms from doxygen generated xml files to html documentation, so unless using doxygen is totally ruled out, that can be used to bridge between the old html pages and generated ones. 2) Doxygen markups are harder to read than ordinary comments (see 3), and in the library headers the volume of such comments will, in many cases, dwarf the amount of code If the code is well written, comments are usually reserved for situations where they are necessary to describe what the code is actually supposed to be doing. Most frequently this type of comment would be found in the body of a function definition. Doxygen comments, on the other hand, usually appear with the declarations, so the type of comments that you would usually need to read aren't necessarily in the same place as the doxygen comments. Additionally, your editor can likely be configured to hide the doxygen comments if you don't want to see them. As for readability, consider this. There are currently no comments describing what a given library class or function is expected to do. If you want to see what the expected behavior is, you get to walk yourself through the implementation, or you get to fire up a web browser and look at the html documentation. If the documentation is added as doxygen comments, they are in the code. They may be slightly less readable than plain english text due to the additional markup, but there is _nothing_ that is stopping you from looking to the implementation or firing up a web browser like you did before. 3) unless/until there is infrastructure to generate the HTML docs from the Doxygen comments documenting the library (or other parts of stdcxx) using Doxygen markups serves no purpose Which would you like first, the chick or the egg? The infrastructure will never be built to generate html documentation from doxygen comments if we don't have doxygen comments to generate documentation from. 4) the HTML generated from stdcxx headers is unavoidably ugly because of the necessity to uglify names (leading underscores, etc.) I thought leading underscores made code run faster. :) Doxygen doesn't have to document everything that it sees. There are many ways to control what will be documented. You can tell it to only generate documentation for things that have doxygen style comments
RE: svn commit: r667636 - /stdcxx/branches/4.3.x/include/rw/_forward.h
-Original Message- From: Martin Sebor [mailto:[EMAIL PROTECTED] Sent: Monday, June 23, 2008 11:38 AM To: dev@stdcxx.apache.org Subject: Re: svn commit: r667636 - /stdcxx/branches/4.3.x/include/rw/_forward.h Eric Lemings wrote: -Original Message- From: Travis Vitek [mailto:[EMAIL PROTECTED] Sent: Monday, June 23, 2008 10:13 AM To: dev@stdcxx.apache.org Subject: RE: svn commit: r667636 - /stdcxx/branches/4.3.x/include/rw/_forward.h Martin Sebor wrote: Eric Lemings wrote: Gah. I have to update my docs as well: template parameters are documented using the @tparam tag rather than the @param tag. I thought we said we wouldn't be using doxygen comments in library code. Am I misremembering? I know that it was requested that I remove the doxygen comments from the type traits stuff I have been working on, but I decided it would be best to commit them with the comments intact and remove them only if necessary. I mentioned this to Brad in our off-list correspondence, and he has opted to do the same. As I sit here thinking about it, I can't remember exactly why it was decided that they should be removed. Perhaps it is best to have this discussion again, but on the list this time. To start, I'm not sure I understand the motivation for _not_ using doxygen in the library headers. I realize that having documentation in the code is a departure from what stdcxx has done in the past, but I'm not convinced that this is a bad thing. I'll add a couple points to that for the record. Much of this was precipitated when I noticed that GNU libstdc++ also includes their documentation right in the library headers and source code. Why? Because most, if not all, C/C++ preprocessors will strip comments by default during a first pass. Thus, the impact of extensive documentation comments on overall build times is negligible. Of course preprocessors strip comments. It's required by the language standards. But regardless of the translation stage at which the stripping takes place, it isn't without cost. I gave a number of arguments against Doxygen comments in stdcxx headers: 1) existing code doesn't use it and converting the raw HTML docs to Doxygen is an enormous task that none of us has the time to take on; Doxygenating new code without doing the same for the existing code is inconsistent and won't help us produce end-user documentation for the finished product What Travis said: if we don't write it ourselves, it probably won't get written. :) I also agree: I'd rather write doc comments than update the existing raw HTML docs. 2) Doxygen markups are harder to read than ordinary comments (see 3), and in the library headers the volume of such comments will, in many cases, dwarf the amount of code That's subjective. Because they are more structured than free-form comments, I find them easier to read. 3) unless/until there is infrastructure to generate the HTML docs from the Doxygen comments documenting the library (or other parts of stdcxx) using Doxygen markups serves no purpose I consider that icing on the cake. You can still generate docs without having them published online. 4) the HTML generated from stdcxx headers is unavoidably ugly because of the necessity to uglify names (leading underscores, etc.) This can be controlled with conditional sections and comments, using @if tags, @internal tags, _RWSTD_EXT_DOXYGEN macro, and other such mechanisms. Brad.
Re: svn commit: r667636 - /stdcxx/branches/4.3.x/include/rw/_forward.h
[EMAIL PROTECTED] wrote: Author: elemings Date: Fri Jun 13 13:16:06 2008 New Revision: 667636 URL: http://svn.apache.org/viewvc?rev=667636view=rev Log: 2008-06-13 Eric Lemings [EMAIL PROTECTED] STDCXX-958 * include/rw/_forward.h: New header file containing initial implementation of std::identity class template; std::forward() and std::move() functions; and internal _RWSTD_MOVE() macro. Added: stdcxx/branches/4.3.x/include/rw/_forward.h Added: stdcxx/branches/4.3.x/include/rw/_forward.h URL: http://svn.apache.org/viewvc/stdcxx/branches/4.3.x/include/rw/_forward.h?rev=667636view=auto == --- stdcxx/branches/4.3.x/include/rw/_forward.h (added) +++ stdcxx/branches/4.3.x/include/rw/_forward.h Fri Jun 13 13:16:06 2008 [...] +template class _Type Please follow the current naming convention for the names of template parameters. +struct identity +{ +/** Identifies template parameter type. */ +typedef _Type type; + +/** + * Conversion operator. This operator converts the parameter value + * to the wrapped identity type. + * + * @param __x An value convertible to identity type. + * @returns Same value as the function argument with identity type. + */ +const _Type operator() (const _Type __x) { The member function is supposed to be const. +return __x; +} +}; + + +#if !defined _RWSTD_NO_RVALUE_REFERENCES + +/** + * Forwards appropriate rvalue or lvalue reference type. This function + * is used to ensure that the appropriate reference type is used in move + * semantics. + * + * @param _Type An lvalue or rvalue reference type. + * @param __x An lvalue reference or rvalue reference. + * @returns An lvalue if __x is an lvalue reference; otherwise, an rvalue. + */ +_EXPORT Only out-of-line templates need to be declared exported. Out-of-line function templates must be defined in .cc files, and .cc files containing exported definitions need to be explicitly #included in export.cpp. This function template as well as move() below should be declared inline. +template class _Type +_Type +forward (_TYPENAME identity_Type::type __x) +{ +return __x; +} + +/** + * Move a value to an rvalue reference. This function is used to + * explicitly bind constructors and other functions with rvalue + * references that employ move semantics. + * + * @param __x An lvalue or rvalue. + * @returns Same value as parameter with rvalue reference type. + */ +_EXPORT +template class _Type +_TYPENAME _RW::__rw_remove_reference_Type::type +move (_Type __x) +{ +return __x; +} + +/** + * @internal + * Internal wrapper macro to utilize move semantics if available. + * @param __x An lvalue or rvalue. + */ +# define _RWSTD_MOVE(__x) std::move (__x) ^ This should be _STD::move (__x). Thanks! Martin +#else // no rvalue references +# define _RWSTD_MOVE(__x) (__x) + +#endif // !defined _RWSTD_NO_RVALUE_REFERENCES + + +} // namespace std + + +# endif // !defined _RWSTD_NO_EXT_CXX_0X + +#endif // _RWSTD_RW_FORWARD_INCLUDED
Re: svn commit: r668225 - /stdcxx/branches/4.3.x/etc/config/src/VA_LIST_FUNC_MACRO.cpp
[EMAIL PROTECTED] wrote: Author: elemings Date: Mon Jun 16 09:31:03 2008 New Revision: 668225 URL: http://svn.apache.org/viewvc?rev=668225view=rev Log: 2008-06-16 Eric Lemings [EMAIL PROTECTED] STDCXX-958 * etc/config/src/VA_LIST_FUNC_MACRO.cpp: Initial version of configuration check for va-list function macros. Out of curiosity, what do you expect to use this for? (FWIW, I've often wished variadic macros were supported in C++ compilers but I could never come up with a workaround for their absence, making them essentially unusable as a general purpose feature.) If we do come up with a use for the feature, I'd like to suggest renaming the config test VARIADIC_MACRO.cpp. Martin
Re: svn commit: r668318 - in /stdcxx/branches/4.3.x: include/rw/_tuple.h include/rw/_tuple_traits.h include/tuple tests/utilities/20.tuple.cnstr.cpp
[EMAIL PROTECTED] wrote: Author: elemings Date: Mon Jun 16 14:16:48 2008 New Revision: 668318 URL: http://svn.apache.org/viewvc?rev=668318view=rev Log: 2008-06-16 Eric Lemings [EMAIL PROTECTED] STDCXX-958 * include/tuple, include/rw/_tuple.h, include/rw/_tuple_traits.h: Add initial version of headers defining tuple interface and implementation. (Only tested on Linux/gcc-4.3 platforms so far.) * tests/utilities/20.tuple.cnstr.cpp: Rough outline of first tuple test program. [...] +#if !defined _RWSTD_NO_VARIADIC_TEMPLATES + + +_RWSTD_NAMESPACE (std) { + + +// 20.3.1, class template tuple: + +/** + * @defgroup tuple Tuples [tuple] + * + * A fixed-size collection of values with variable, heterogenous types. + * This class template is used to instantatiate tuple types. A tuple + * type specifies zero or more element types for defining tuple values. + * A tuple value can be constructed from a tuple type that holds one + * value for each element type in the tuple. + * + * @param Types A list of zero or more types. No applicable type + * requirements or restrictions. + */ +template class... Types Please follow the established convention and drop the spaces before class and before the closing pointy brace. Thanks! :) +class tuple; + +/** + * @internal + * The template specialization for empty tuples. + */ +_RWSTD_SPECIALIZED_CLASS +class tuple Also please remove the space between the pointy braces here. +{ +// empty +}; + +/** + * @internal + * The basic template specialization for most tuples. This class + * template is used to instantiate all tuple types except for empty + * tuples and tuples with exactly two element types. + * + * @param _HeadT First element type (required). + * @param _TailT Template parameter pack for remaining element types. + */ +template class _HeadT, class... _TailT In the interest of consistency we should adopt the same naming convention for the names of variadic template parameters. We have _TypeT and and Types in traits, _HeadT and _TailT here, and TTypes and UTypes in the standard. Which one should it be? +class tuple _HeadT, _TailT... +: tuple _TailT... +{ +typedef tuple _TailT... _Base; + +protected: + +_HeadT _C_head; Why protected and not private? + +public: + +/** + * Construct tuple with default values. + */ +tuple () +: _C_head (), _Base () { /* empty */ } Unless tuple is somehow different from other (non-variadic classes) I think _Base() here should be listed first, because it's initialized first, no? + +/** + * Copy construct tuple from a different tuple value. + * @param __tuple Another tuple value with same type. + */ +tuple (const tuple __tuple) +: _C_head (__tuple._C_head), _Base (__tuple) { /* empty */ } Same as above. + +/** + * Copy assign tuple from a different tuple value. + * @param __tuple Another tuple value with same type. + */ +tuple operator= (const tuple __tuple) { +_C_head = __tuple._C_head; +_Base::operator= (__tuple); Similarly to the ctor, the base assignment operator should probably be invoked first. +return *this; +} + +_EXPLICIT +tuple (const _HeadT __head, const _TailT... __tail) +: _C_head (__head), _Base (__tail...) { /* empty */ } + +# if !defined _RWSTD_NO_RVALUE_REFERENCES + +tuple (tuple __tuple) +: _C_head (std::move (__tuple._C_head)) +, _Base (std::forward_Base (__tuple)) { /* empty */ } The initialization order should follow the default ctor case (i.e., _Base first). Also, the existing convention doesn't drop the comma. + +tuple operator= (tuple __tuple) { +_C_head = std::move (__tuple._C_head); +_Base::operator= (__tuple); Same as the other assignment operator. Also, I think it would make the class easier to read if overloads were kept together wherever possible (i.e., all ctors, all assignment operators, etc.) Although I think I see why you didn't -- to avoid duplicating the rvalue references test. Hmm. Have we decided on the list of required compiler features yet? I saw your Compiler Requirements page on the wiki (thanks for starting it, btw.) and rvalue references isn't there. Do we think we can provide a useful implementation of C++ 0x without rvalue references? +return *this; +} + +# endif // !defined _RWSTD_NO_RVALUE_REFERENCES + +# if !defined _RWSTD_NO_MEMBER_TEMPLATES I think we can safely rely on member templates in C++ 0x. Do we all agree? [...] Added: stdcxx/branches/4.3.x/include/rw/_tuple_traits.h [...] +template class _Type +struct constructible_with_allocator_prefix; + +/** + * Allows tuple construction with an allocator prefix argument. This + * trait informs other library components that tuple can be constructed + * with an allocator preï¬x argument. Looks like an
RE: svn commit: r668225 - /stdcxx/branches/4.3.x/etc/config/src/VA_LIST_FUNC_MACRO.cpp
-Original Message- From: Martin Sebor [mailto:[EMAIL PROTECTED] Sent: Monday, June 23, 2008 2:10 PM To: dev@stdcxx.apache.org Subject: Re: svn commit: r668225 - /stdcxx/branches/4.3.x/etc/config/src/VA_LIST_FUNC_MACRO.cpp [EMAIL PROTECTED] wrote: Author: elemings Date: Mon Jun 16 09:31:03 2008 New Revision: 668225 URL: http://svn.apache.org/viewvc?rev=668225view=rev Log: 2008-06-16 Eric Lemings [EMAIL PROTECTED] STDCXX-958 * etc/config/src/VA_LIST_FUNC_MACRO.cpp: Initial version of configuration check for va-list function macros. Out of curiosity, what do you expect to use this for? (FWIW, I've often wished variadic macros were supported in C++ compilers but I could never come up with a workaround for their absence, making them essentially unusable as a general purpose feature.) The most obvious use would be in RWTest printf-like functions. I'm not sure how well variadic function macros mesh with variadic templates but, if they do, I could take advantage of the feature in tuples. In any case, I figured we'll need the config test sooner or later. If we do come up with a use for the feature, I'd like to suggest renaming the config test VARIADIC_MACRO.cpp. Fine by me. :) Brad.
Re: svn commit: r668225 - /stdcxx/branches/4.3.x/etc/config/src/VA_LIST_FUNC_MACRO.cpp
Eric Lemings wrote: -Original Message- From: Martin Sebor [mailto:[EMAIL PROTECTED] Sent: Monday, June 23, 2008 2:10 PM To: dev@stdcxx.apache.org Subject: Re: svn commit: r668225 - /stdcxx/branches/4.3.x/etc/config/src/VA_LIST_FUNC_MACRO.cpp [EMAIL PROTECTED] wrote: Author: elemings Date: Mon Jun 16 09:31:03 2008 New Revision: 668225 URL: http://svn.apache.org/viewvc?rev=668225view=rev Log: 2008-06-16 Eric Lemings [EMAIL PROTECTED] STDCXX-958 * etc/config/src/VA_LIST_FUNC_MACRO.cpp: Initial version of configuration check for va-list function macros. Out of curiosity, what do you expect to use this for? (FWIW, I've often wished variadic macros were supported in C++ compilers but I could never come up with a workaround for their absence, making them essentially unusable as a general purpose feature.) The most obvious use would be in RWTest printf-like functions. I'm not sure how well variadic function macros mesh with variadic templates but, if they do, I could take advantage of the feature in tuples. My point was that I couldn't find a way to use a feature that depends on variadic macros on platforms where they are not supported. In other words, I can't picture what the #else branch below would look like: #ifndef _RWSTD_NO_VARIADIC_MACROS # define RW_ASSERT(expr, ...) \ rw_assert (expr, 0, __LINE__, __VA_LIST__) #else # define RW_ASSERT(expr, ???) ... #endif Martin In any case, I figured we'll need the config test sooner or later. If we do come up with a use for the feature, I'd like to suggest renaming the config test VARIADIC_MACRO.cpp. Fine by me. :) Brad.
RE: tests/utilities/20.meta.help.cpp
Martin Sebor wrote: Travis Vitek wrote: Eric Lemings wrote: Just a brief side note. I was just reviewing this test and noticed that pointers are not tested though they are valid scalar types suitable for use as integral_constant parameters. I think references may be valid parameters also. I'm not sure. The first thing that jumps to mind is that a pointer is not of 'integral' type. An enumeration isn't really an integral type either, but they are implicitly convertible to one. Pointers aren't convertible to integral type without a cast. According to temp.arg.nontype, a non-type, non-template template parameter must be one of -- an integral constant expression -- the name of a non-type template-parameter -- the address of an object or function with external linkage... -- a constant expression that evaluates to a null pointer value -- a constant expression that evaluates to a null member pointer value -- a pointer to member So, yes, it is legal to use a pointer as a non-type template parameter. The issue I have is that the integral_constantT,V is supposed to define an integral constant of type T with value V. Section expr.const says that a constant expression is an integral constant expression if it is of integral or enumeration type. An integral constant expression can be used as an array bound, a case expression, a bit field length, enumeration initializer, static member initializer and as integral or enumeration non-type template arguments. I'm pretty sure you can't use a pointer value as an array bound, case expression, bit field length or enumeration initializer, so they aren't really integral constants. So I am sure you can instantiate std::integral_constantvoid (class_t::*)(), class::method, but I'm not sure if it something that should be tested. If there's an implementation technique that would make the instantiation ill-formed then I think it should be tested. According to class.mem (p4) and class.static.data (p4) you aren't allowed to initialize static members using a constant-initializer (i.e. in the member declaration) if they are not of const integral or const enumeration type. So the above instantiation on member pointer should be prevented by the compiler. A quick test with msvc-8.0 and gcc-4.3 show that this is the case. The following would be legal, but I'm already testing integral constants for all integral types and an enum type, so I think I'm covered. More important, though, the standard should specify the requirements on the template arguments. If there are no such requirements for something as fundamental as integral_const, either in the latest working draft or in one of the concepts papers (such as N2622), we should at least bring it up on the list and/or open an issue to have the spec clarified. The standard does specify the requirements of the template arguments, but only through association (to be an integral constant member, it has to be a const static that is initialized with a constant-initializer, and a constant initializer only works for enum and integral types). Is this significant enough to warrant bringing up an issue? Travis
RE: svn commit: r668318 - in /stdcxx/branches/4.3.x: include/rw/_tuple.h include/rw/_tuple_traits.h include/tuple tests/utilities/20.tuple.cnstr.cpp
-Original Message- From: Martin Sebor [mailto:[EMAIL PROTECTED] Sent: Monday, June 23, 2008 3:02 PM To: dev@stdcxx.apache.org Subject: Re: svn commit: r668318 - in /stdcxx/branches/4.3.x: include/rw/_tuple.h include/rw/_tuple_traits.h include/tuple tests/utilities/20.tuple.cnstr.cpp [EMAIL PROTECTED] wrote: Author: elemings Date: Mon Jun 16 14:16:48 2008 New Revision: 668318 URL: http://svn.apache.org/viewvc?rev=668318view=rev Log: 2008-06-16 Eric Lemings [EMAIL PROTECTED] STDCXX-958 * include/tuple, include/rw/_tuple.h, include/rw/_tuple_traits.h: Add initial version of headers defining tuple interface and implementation. (Only tested on Linux/gcc-4.3 platforms so far.) * tests/utilities/20.tuple.cnstr.cpp: Rough outline of first tuple test program. [...] +#if !defined _RWSTD_NO_VARIADIC_TEMPLATES + + +_RWSTD_NAMESPACE (std) { + + +// 20.3.1, class template tuple: + +/** + * @defgroup tuple Tuples [tuple] + * + * A fixed-size collection of values with variable, heterogenous types. + * This class template is used to instantatiate tuple types. A tuple + * type specifies zero or more element types for defining tuple values. + * A tuple value can be constructed from a tuple type that holds one + * value for each element type in the tuple. + * + * @param Types A list of zero or more types. No applicable type + * requirements or restrictions. + */ +template class... Types Please follow the established convention and drop the spaces before class and before the closing pointy brace. Thanks! :) It would be a lot easier if these conventions were actually ESTABLISHED. Until they are established, we're going to be constantly running into this problem. Don't you agree? I can start a Wiki page for this unless you'd prefer to do it. +class tuple; + +/** + * @internal + * The template specialization for empty tuples. + */ +_RWSTD_SPECIALIZED_CLASS +class tuple Also please remove the space between the pointy braces here. +{ +// empty +}; + +/** + * @internal + * The basic template specialization for most tuples. This class + * template is used to instantiate all tuple types except for empty + * tuples and tuples with exactly two element types. + * + * @param _HeadT First element type (required). + * @param _TailT Template parameter pack for remaining element types. + */ +template class _HeadT, class... _TailT In the interest of consistency we should adopt the same naming convention for the names of variadic template parameters. We have _TypeT and and Types in traits, _HeadT and _TailT here, and TTypes and UTypes in the standard. Which one should it be? It is my opinion that the T and U prefixes/suffixes are only necessary in binary contexts; i.e. where there are two different types or type lists. Otherwise, we should use just a plain Type name. Furthermore, generic Type names should only be used in truly generic contexts; i.e. contexts where just about any type can be used. Otherwise, the name should imply the restrictions/requirements on the type; e.g. _ScalarType, _IntConst. In the recursive tuple case, using generic names would make the code much harder to follow IMHO. +class tuple _HeadT, _TailT... +: tuple _TailT... +{ +typedef tuple _TailT... _Base; + +protected: + +_HeadT _C_head; Why protected and not private? Good point. Given there's an internal accessor now, this could be private I think. + +public: + +/** + * Construct tuple with default values. + */ +tuple () +: _C_head (), _Base () { /* empty */ } Unless tuple is somehow different from other (non-variadic classes) I think _Base() here should be listed first, because it's initialized first, no? Yep. I think these were all done in a subsequent change. + +/** + * Copy construct tuple from a different tuple value. + * @param __tuple Another tuple value with same type. + */ +tuple (const tuple __tuple) +: _C_head (__tuple._C_head), _Base (__tuple) { /* empty */ } Same as above. + +/** + * Copy assign tuple from a different tuple value. + * @param __tuple Another tuple value with same type. + */ +tuple operator= (const tuple __tuple) { +_C_head = __tuple._C_head; +_Base::operator= (__tuple); Similarly to the ctor, the base assignment operator should probably be invoked first. +return *this; +} + +_EXPLICIT +tuple (const _HeadT __head, const _TailT... __tail) +: _C_head (__head), _Base (__tail...) { /* empty */ } + +# if !defined _RWSTD_NO_RVALUE_REFERENCES + +tuple (tuple __tuple) +: _C_head (std::move (__tuple._C_head)) +, _Base (std::forward_Base
RE: svn commit: r668225 - /stdcxx/branches/4.3.x/etc/config/src/VA_LIST_FUNC_MACRO.cpp
-Original Message- From: Martin Sebor [mailto:[EMAIL PROTECTED] Sent: Monday, June 23, 2008 3:50 PM To: dev@stdcxx.apache.org Subject: Re: svn commit: r668225 - /stdcxx/branches/4.3.x/etc/config/src/VA_LIST_FUNC_MACRO.cpp Eric Lemings wrote: -Original Message- From: Martin Sebor [mailto:[EMAIL PROTECTED] Sent: Monday, June 23, 2008 2:10 PM To: dev@stdcxx.apache.org Subject: Re: svn commit: r668225 - /stdcxx/branches/4.3.x/etc/config/src/VA_LIST_FUNC_MACRO.cpp [EMAIL PROTECTED] wrote: Author: elemings Date: Mon Jun 16 09:31:03 2008 New Revision: 668225 URL: http://svn.apache.org/viewvc?rev=668225view=rev Log: 2008-06-16 Eric Lemings [EMAIL PROTECTED] STDCXX-958 * etc/config/src/VA_LIST_FUNC_MACRO.cpp: Initial version of configuration check for va-list function macros. Out of curiosity, what do you expect to use this for? (FWIW, I've often wished variadic macros were supported in C++ compilers but I could never come up with a workaround for their absence, making them essentially unusable as a general purpose feature.) The most obvious use would be in RWTest printf-like functions. I'm not sure how well variadic function macros mesh with variadic templates but, if they do, I could take advantage of the feature in tuples. My point was that I couldn't find a way to use a feature that depends on variadic macros on platforms where they are not supported. In other words, I can't picture what the #else branch below would look like: #ifndef _RWSTD_NO_VARIADIC_MACROS # define RW_ASSERT(expr, ...) \ rw_assert (expr, 0, __LINE__, __VA_LIST__) #else # define RW_ASSERT(expr, ???) ... #endif You're right. There is no backward-compatible workaround which essentially rules out using variadic macros in these cases. Brad.
RE: svn commit: r668225 - /stdcxx/branches/4.3.x/etc/config/src/VA_LIST_FUNC_MACRO.cpp
Eric Lemings wrote: Martin Sebor wrote: My point was that I couldn't find a way to use a feature that depends on variadic macros on platforms where they are not supported. In other words, I can't picture what the #else branch below would look like: #ifndef _RWSTD_NO_VARIADIC_MACROS # define RW_ASSERT(expr, ...) \ rw_assert (expr, 0, __LINE__, __VA_LIST__) #else # define RW_ASSERT(expr, ???) ... #endif You're right. There is no backward-compatible workaround which essentially rules out using variadic macros in these cases. I think I've showed this trick before, but it won't work with template parameters, only function parameters. struct Variadic { void operator()(const char* fmt, ...); }; #define VARIADIC Variadic().operator() Of course you would use it like this... VARIADIC(hello %s, world!); Travis Brad.
Re: svn commit: r668225 - /stdcxx/branches/4.3.x/etc/config/src/VA_LIST_FUNC_MACRO.cpp
Eric Lemings wrote: -Original Message- From: Travis Vitek [mailto:[EMAIL PROTECTED] Sent: Monday, June 23, 2008 4:59 PM To: dev@stdcxx.apache.org Subject: RE: svn commit: r668225 - /stdcxx/branches/4.3.x/etc/config/src/VA_LIST_FUNC_MACRO.cpp Eric Lemings wrote: Martin Sebor wrote: My point was that I couldn't find a way to use a feature that depends on variadic macros on platforms where they are not supported. In other words, I can't picture what the #else branch below would look like: #ifndef _RWSTD_NO_VARIADIC_MACROS # define RW_ASSERT(expr, ...) \ rw_assert (expr, 0, __LINE__, __VA_LIST__) #else # define RW_ASSERT(expr, ???) ... #endif You're right. There is no backward-compatible workaround which essentially rules out using variadic macros in these cases. Which is why I don't think we'll be able to (or need to) use the config macro in our code. I think I've showed this trick before, but it won't work with template parameters, only function parameters. Right. This trick obviates the need for variadic macros in the case of the rw_xxx() functions. (Note that the trick isn't a general replacement for variadic macros because it relies on a runtime mechanism while variadic macros are a compile-time one.) struct Variadic { void operator()(const char* fmt, ...); }; #define VARIADIC Variadic().operator() Of course you would use it like this... VARIADIC(hello %s, world!); Had forgotten about that. :) So, we have something like this: There's no need for the additional complexity when we can just use the #else case unconditionally. The !_RWSTD_NO_VARIADIC_MACROS case provides no advantage over the workaround. #ifndef _RWSTD_NO_VARIADIC_MACROS # define RW_ASSERT(expr, ...) \ rw_assert (expr, 0, __LINE__, __VA_LIST__) #else struct __rw_assert { int operator()(int expr, const char* file, int line, const char* fmt, ...) { va_list va; va_start (va, fmt); _rw_vdiag (diag_assert, 0 == expr, file, line, fmt, va); va_end (va); return success; } }; # define RW_ASSERT __rw_assert().operator() #endif That pretty close? And why is there a 2nd parameter in rw_assert() if its never used? :P Brad.
Re: svn commit: r668318 - in /stdcxx/branches/4.3.x: include/rw/_tuple.h include/rw/_tuple_traits.h include/tuple tests/utilities/20.tuple.cnstr.cpp
Eric Lemings wrote: [...] Please follow the established convention and drop the spaces before class and before the closing pointy brace. Thanks! :) It would be a lot easier if these conventions were actually ESTABLISHED. Until they are established, we're going to be constantly running into this problem. Don't you agree? They are fully established (grep for class vs class in our sources), they're just not formally documented. In the absence of documentation I suggest you follow the style used in existing code. It's not that different from the style used in most other projects including those at Rogue Wave. I can start a Wiki page for this unless you'd prefer to do it. Starting a page on coding style sounds like a great idea. [...] +template class _HeadT, class... _TailT In the interest of consistency we should adopt the same naming convention for the names of variadic template parameters. We have _TypeT and and Types in traits, _HeadT and _TailT here, and TTypes and UTypes in the standard. Which one should it be? It is my opinion that the T and U prefixes/suffixes are only necessary in binary contexts; i.e. where there are two different types or type lists. That may be the case but... Otherwise, we should use just a plain Type name. ...we have an established convention that has the T at the end. I'm opposed to using different conventions for new vs existing code and I see no compelling reason to change the thousands of lines of existing code to conform to a different convention. What I'd like us to do is establish a convention to use for variadic templates. The convention that makes the most sense to me is one that builds on the existing convention for ordinary (non-variadic) templates. Of the three choices that I gave initially: template class _TypeT, class... _Types // in type traits template class _HeadT, class... _TailT // in tuple template class _TType, class... _UTypes// in the spec the one that fits the bill is the first one: template class _TypeT, class... _Types We can tweak the name of the parameter pack but I don't see how we can change the name of the first parameter without deviating from the current convention. Furthermore, generic Type names should only be used in truly generic contexts; i.e. contexts where just about any type can be used. Otherwise, the name should imply the restrictions/requirements on the type; e.g. _ScalarType, _IntConst. In the recursive tuple case, using generic names would make the code much harder to follow IMHO. For the non-variadic case this is quite elegantly handled by concepts. For example, the new variadic function template std::min() currently declared in the working paper like so: template class T, ... Args const T min (const T a, const Args... args); becomes: template LessThanComparable T, LessThanComparable... Args requires SameTypeT, Args... const T min (const T a , const Args... args); [...] +template int _Index, class ... _Types +_TYPENAME tuple_element_Index, tuple_Types... ::type const The const should come before tuple_element. For style? They are semantically equivalent though, aren't they? BTW, this is how it is specified in the draft. Yes, we discussed consistency at the last meeting. IIUC, the editor is going to make the appropriate changes to bring the new text into accord with the existing convention (i.e., change T const to const T). Martin
Re: tests/utilities/20.meta.help.cpp
Travis Vitek wrote: Martin Sebor wrote: Travis Vitek wrote: Eric Lemings wrote: Just a brief side note. I was just reviewing this test and noticed that pointers are not tested though they are valid scalar types suitable for use as integral_constant parameters. I think references may be valid parameters also. I'm not sure. The first thing that jumps to mind is that a pointer is not of 'integral' type. An enumeration isn't really an integral type either, but they are implicitly convertible to one. Pointers aren't convertible to integral type without a cast. According to temp.arg.nontype, a non-type, non-template template parameter must be one of -- an integral constant expression -- the name of a non-type template-parameter -- the address of an object or function with external linkage... -- a constant expression that evaluates to a null pointer value -- a constant expression that evaluates to a null member pointer value -- a pointer to member So, yes, it is legal to use a pointer as a non-type template parameter. The issue I have is that the integral_constantT,V is supposed to define an integral constant of type T with value V. Section expr.const says that a constant expression is an integral constant expression if it is of integral or enumeration type. An integral constant expression can be used as an array bound, a case expression, a bit field length, enumeration initializer, static member initializer and as integral or enumeration non-type template arguments. I'm pretty sure you can't use a pointer value as an array bound, case expression, bit field length or enumeration initializer, so they aren't really integral constants. So I am sure you can instantiate std::integral_constantvoid (class_t::*)(), class::method, but I'm not sure if it something that should be tested. If there's an implementation technique that would make the instantiation ill-formed then I think it should be tested. According to class.mem (p4) and class.static.data (p4) you aren't allowed to initialize static members using a constant-initializer (i.e. in the member declaration) if they are not of const integral or const enumeration type. So the above instantiation on member pointer should be prevented by the compiler. A quick test with msvc-8.0 and gcc-4.3 show that this is the case. Good point! The following would be legal, but I'm already testing integral constants for all integral types and an enum type, so I think I'm covered. More important, though, the standard should specify the requirements on the template arguments. If there are no such requirements for something as fundamental as integral_const, either in the latest working draft or in one of the concepts papers (such as N2622), we should at least bring it up on the list and/or open an issue to have the spec clarified. The standard does specify the requirements of the template arguments, but only through association (to be an integral constant member, it has to be a const static that is initialized with a constant-initializer, Is this specified anywhere else besides the definition of the class in [meta.help]? If not, I'm not sure that every detail of a class definition shown in the spec qualifies as a normative requirement. and a constant initializer only works for enum and integral types). Is this significant enough to warrant bringing up an issue? IMO, the class should have an explicit requirement on the first template argument. If there isn't one I would propose adding paragraph 2 with the text: -2- The template parameter T shall have an integral type (3.9.1). integral_constantT::value shall be a integral constant expression (5.19). With concepts, we would change the definition of the class like this (I think): template IntegralConstantExpressionType T, T v struct integral_constant { // ... }; Strangely, this isn't in N2625: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2625.pdf Incidentally, it also seems to me that value should be declared constexpr (both in our implementation and in the spec). Travis