This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: c++0x vs. tr1 type_traits, round 1


On Thu, 2007-04-26 at 17:14 +0200, Benjamin Kosnik wrote:
> > Therefore I would ask you to go ahead with something straighforward, as 
> > we discussed above: set-up a separate implementation of type_traits for 
> > C++0x by copying the current TR1 one, adjusting the names of those 4 
> > traits discussed between yesterday and today, adding the new traits. 
> 
> Yeah, well.... this doesn't work.
> 
> :(
[snip]
> This is striking me more and more as the wrong path. Maybe 
> _GLIBCXX_SUPPRESS_TR1 is the way to go after all...

So, let's step back a bit. 

TR1 and C++0x have a lot of code in common, so we don't want to maintain
two completely different copies of essentially the same source code. 

Now, TR1 has some things that C++0x does not, and C++0x has some things
that TR1 does not, so we need some level of customization for each
library variant. There are two important aspects to this customization:
(1) both variants can occur in the same translation unit, and therefore
must be separated somehow; and (2) this customization has very little to
do with the source language that the compiler is processing, e.g., TR1
bind can use rvalue references if we're in C++0x mode, but not when
we're in C++98 mode.

I think (1) precludes the use of namespace association for sharing code
(because the variants must be distinct) and (2) precludes any scheme
that involves customizing tr1/headers via __GXX_EXPERIMENTAL_CXX0X__.

One solution is to move all of the common code into a separate place,
e.g., include/tr1_impl/type_traits. It would then be included in
different ways from include/std/type_traits and
include/tr1/type_traits. 

include/tr1_impl/type_traits might look like this:

namespace std 
{
_GLIBCXX_TR1_NAMESPACE_BEGIN

  // Bits common to C++0x and TR1
  // Where necessary, use _GLIBCXX_INCLUDE_AS_CXX0X or
  // _GLIBCXX_INCLUDE_AS_TR1 to handle variations

_GLIBCXX_TR1_NAMESPACE_END
}


Then, include/std/type_traits would look like this:

#if defined(_GLIBCXX_INCLUDE_AS_TR1)
#  error C++0x header cannot be included from TR1 header
#endif

#ifndef _GLIBCXX_CXX0X_TYPE_TRAITS_H
#define _GLIBCXX_CXX0X_TYPE_TRAITS_H 1

#if defined(_GLIBCXX_INCLUDE_AS_CXX0X)
#  include <tr1_impl/type_traits>
#else
#  define _GLIBCXX_INCLUDE_AS_CXX0X
#  define _GLIBCXX_TR1_NAMESPACE_BEGIN
#  define _GLIBCXX_TR1_NAMESPACE_END
#  include <tr1_impl/type_traits>
#  undef _GLIBCXX_TR1_NAMESPACE_END
#  undef _GLIBCXX_TR1_NAMESPACE_BEGIN
#  undef _GLIBCXX_INCLUDE_AS_CXX0X
#endif

namespace std
{
  // C++0x-specific bits
}
#endif // _GLIBCXX_CXX0X_TYPE_TRAITS_H


Finally, include/tr1/type_traits would be:

#if defined(_GLIBCXX_INCLUDE_AS_CXX0X)
#  error TR1 header cannot be included from C++0x header
#endif

#ifndef _GLIBCXX_TR1_TYPE_TRAITS_H
#define _GLIBCXX_TR1_TYPE_TRAITS_H 1

#if defined(_GLIBCXX_INCLUDE_AS_TR1)
#  include <tr1_impl/type_traits>
#else
#  define _GLIBCXX_INCLUDE_AS_TR1
#  define _GLIBCXX_TR1_NAMESPACE_BEGIN namespace tr1 {
#  define _GLIBCXX_TR1_NAMESPACE_END }
#  include <tr1_impl/type_traits>
#  undef _GLIBCXX_TR1_NAMESPACE_END
#  undef _GLIBCXX_TR1_NAMESPACE_BEGIN
#  undef _GLIBCXX_INCLUDE_AS_TR1
#endif

namespace std
{
namespace tr1
{
  // TR1-specific bits
}
}
#endif // _GLIBCXX_TR1_TYPE_TRAITS_H

Now, this does mean that headers in tr1_impl won't really be able to
include other headers without doing the dance Benjamin was talking
about:

// in include/tr1_impl/functional:

#if defined(_GLIBCXX_INCLUDE_AS_CXX0X)
#  include <type_traits>
#else
#  include <tr1/type_traits>
#endif

In this case (perhaps in all cases?) we could just put the includes
needed by include/tr1_impl/functional into include/std/functional and
include/tr1/functional. If the tr1_impl headers don't include anything,
it becomes easier to avoid C++0x/TR1 collisions.

Does this approach seem reasonable? It feels like a sledgehammer, but at
this point I think that nothing short of this sledgehammer---or
completely separating the TR1 implementation from the C++0x
implementation---will do.

  - Doug


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]