diff --git a/c++_type_traits.htm b/c++_type_traits.htm new file mode 100644 index 0000000..59f188d --- /dev/null +++ b/c++_type_traits.htm @@ -0,0 +1,590 @@ + + + + + + +C++ Type traits + + + + +

C++ Type traits

+ +

by John Maddock and Steve Cleary

+ +

This is the draft version of an article +that appeared in the October 2000 issue of Dr Dobb's Journal

+ +

Generic programming (writing code which works with any data +type meeting a set of requirements) has become the method of +choice for providing reusable code. However, there are times in +generic programming when "generic" just isn't good +enough - sometimes the differences between types are too large +for an efficient generic implementation. This is when the traits +technique becomes important - by encapsulating those properties +that need to be considered on a type by type basis inside a +traits class, we can minimise the amount of code that has to +differ from one type to another, and maximise the amount of +generic code.

+ +

Consider an example: when working with character strings, one +common operation is to determine the length of a null terminated +string. Clearly it's possible to write generic code that can do +this, but it turns out that there are much more efficient methods +available: for example, the C library functions strlen and wcslen are usually written in assembler, +and with suitable hardware support can be considerably faster +than a generic version written in C++. The authors of the C++ +standard library realised this, and abstracted the properties of char and wchar_t into the class char_traits. Generic code that works +with character strings can simply use char_traits<>::length to +determine the length of a null terminated string, safe in the +knowledge that specialisations of char_traits will use the most +appropriate method available to them.

+ +

Type traits

+ +

Class char_traits is +a classic example of a collection of type specific properties +wrapped up in a single class - what Nathan Myers termed a baggage +class[1]. In the Boost type-traits library, we[2] have +written a set of very specific traits classes, each of which +encapsulate a single trait from the C++ type system; for example, +is a type a pointer or a reference type? Or does a type have a +trivial constructor, or a const-qualifier? The type-traits +classes share a unified design: each class has a single member value, +a compile-time constant that is true if the type has the +specified property, and false otherwise. As we will show, these +classes can be used in generic programming to determine the +properties of a given type and introduce optimisations that are +appropriate for that case.

+ +

The type-traits library also contains a set of classes that +perform a specific transformation on a type; for example, they +can remove a top-level const or volatile qualifier from a type. +Each class that performs a transformation defines a single +typedef-member type that is the result of the +transformation. All of the type-traits classes are defined inside +namespace boost; for +brevity, namespace-qualification is omitted in most of the code +samples given.

+ +

Implementation

+ +

There are far too many separate classes contained in the type-traits +library to give a full implementation here - see the source code +in the Boost library for the full details - however, most of the +implementation is fairly repetitive anyway, so here we will just +give you a flavour for how some of the classes are implemented. +Beginning with possibly the simplest class in the library, is_void<T> +has a member value that is true only if T is void.

+ +
template <typename T> 
+struct is_void
+{ static const bool value = false; };
+
+template <> 
+struct is_void<void>
+{ static const bool value = true; };
+ +

Here we define a primary version of the template class is_void, and provide a full-specialisation +when T is void. While full specialisation of a template class is +an important technique, sometimes we need a solution that is +halfway between a fully generic solution, and a full +specialisation. This is exactly the situation for which the +standards committee defined partial template-class specialisation. +As an example, consider the class boost::is_pointer<T>: +here we needed a primary version that handles all the cases where +T is not a pointer, and a partial specialisation to handle all +the cases where T is a pointer:

+ +
template <typename T> 
+struct is_pointer 
+{ static const bool value = false; };
+
+template <typename T> 
+struct is_pointer<T*> 
+{ static const bool value = true; };
+ +

The syntax for partial specialisation is somewhat arcane and +could easily occupy an article in its own right; like full +specialisation, in order to write a partial specialisation for a +class, you must first declare the primary template. The partial +specialisation contains an extra <…> after the class +name that contains the partial specialisation parameters; these +define the types that will bind to that partial specialisation +rather than the default template. The rules for what can appear +in a partial specialisation are somewhat convoluted, but as a +rule of thumb if you can legally write two function overloads of +the form:

+ +
void foo(T);
+void foo(U);
+ +

Then you can also write a partial specialisation of the form:

+ +
template <typename T>
+class c{ /*details*/ };
+
+template <typename T>
+
+class c<U>{ /*details*/ };
+ +

This rule is by no means foolproof, but it is reasonably +simple to remember and close enough to the actual rule to be +useful for everyday use.

+ +

As a more complex example of partial specialisation consider +the class remove_bounds<T>. This class defines a single +typedef-member type that is the same type as T but with +any top-level array bounds removed; this is an example of a +traits class that performs a transformation on a type:

+ +
template <typename T> 
+struct remove_bounds
+{ typedef T type; };
+
+template <typename T, std::size_t N> 
+struct remove_bounds<T[N]>
+{ typedef T type; };
+ +

The aim of remove_bounds is this: imagine a generic algorithm +that is passed an array type as a template parameter, remove_bounds provides a means +of determining the underlying type of the array. For example remove_bounds<int[4][5]>::type +would evaluate to the type int[5]. This example also +shows that the number of template parameters in a partial +specialisation does not have to match the number in the default +template. However, the number of parameters that appear after the +class name do have to match the number and type of the parameters +in the default template.

+ +

Optimised copy

+ +

As an example of how the type traits classes can be used, +consider the standard library algorithm copy:

+ +
template<typename Iter1, typename Iter2>
+Iter2 copy(Iter1 first, Iter1 last, Iter2 out);
+ +

Obviously, there's no problem writing a generic version of +copy that works for all iterator types Iter1 and Iter2; however, +there are some circumstances when the copy operation can best be +performed by a call to memcpy. +In order to implement copy in terms of memcpy all of the following conditions +need to be met:

+ + + +

By trivial assignment operator we mean that the type is either +a scalar type[3] or:

+ + + +

If all these conditions are met then a type can be copied +using memcpy rather than +using a compiler generated assignment operator. The type-traits +library provides a class has_trivial_assign, such that has_trivial_assign<T>::value +is true only if T has a trivial assignment operator. This class +"just works" for scalar types, but has to be explicitly +specialised for class/struct types that also happen to have a +trivial assignment operator. In other words if has_trivial_assign +gives the wrong answer, it will give the "safe" wrong +answer - that trivial assignment is not allowable.

+ +

The code for an optimised version of copy that uses memcpy where appropriate is +given in listing 1. The code begins by defining a template class copier, +that takes a single Boolean template parameter, and has a static +template member function do_copy +which performs the generic version of copy +(in other words the "slow but safe version"). Following +that there is a specialisation for copier<true>: +again this defines a static template member function do_copy, but this version uses +memcpy to perform an "optimised" copy.

+ +

In order to complete the implementation, what we need now is a +version of copy, that calls copier<true>::do_copy +if it is safe to use memcpy, +and otherwise calls copier<false>::do_copy to +do a "generic" copy. This is what the version in +listing 1 does. To understand how the code works look at the code +for copy and consider +first the two typedefs v1_t and v2_t. These use std::iterator_traits<Iter1>::value_type +to determine what type the two iterators point to, and then feed +the result into another type-traits class remove_cv that +removes the top-level const-volatile-qualifiers: this will allow +copy to compare the two types without regard to const- or +volatile-qualifiers. Next, copy +declares an enumerated value can_opt that will become the +template parameter to copier - declaring this here as a constant +is really just a convenience - the value could be passed directly +to class copier. The +value of can_opt is computed by verifying that all of the +following are true:

+ + + +

Finally we can use the value of can_opt as the template +argument to copier - this version of copy will now adapt to +whatever parameters are passed to it, if its possible to use memcpy, then it will do so, +otherwise it will use a generic copy.

+ +

Was it worth it?

+ +

It has often been repeated in these columns that "premature +optimisation is the root of all evil" [4]. So the question +must be asked: was our optimisation premature? To put this in +perspective the timings for our version of copy compared a +conventional generic copy[5] are shown in table 1.

+ +

Clearly the optimisation makes a difference in this case; but, +to be fair, the timings are loaded to exclude cache miss effects +- without this accurate comparison between algorithms becomes +difficult. However, perhaps we can add a couple of caveats to the +premature optimisation rule:

+ + + +

Table 1: Time taken to copy 1000 elements using copy<const +T*, T*> (times in micro-seconds)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +

Version

+

T

+

Time

+
"Optimised" copychar0.99
Conventional copychar8.07
"Optimised" copyint2.52
Conventional copyint8.02
+ +

 

+ +

Pair of References

+ +

The optimised copy example shows how type traits may be used +to perform optimisation decisions at compile-time. Another +important usage of type traits is to allow code to compile that +otherwise would not do so unless excessive partial specialization +is used. This is possible by delegating partial specialization to +the type traits classes. Our example for this form of usage is a +pair that can hold references [6].

+ +

First, let us examine the definition of "std::pair", +omitting the comparision operators, default constructor, and +template copy constructor for simplicity:

+ +
template <typename T1, typename T2> 
+struct pair 
+{
+  typedef T1 first_type;
+  typedef T2 second_type;
+
+  T1 first;
+  T2 second;
+
+  pair(const T1 & nfirst, const T2 & nsecond)
+  :first(nfirst), second(nsecond) { }
+};
+ +

Now, this "pair" cannot hold references as it +currently stands, because the constructor would require taking a +reference to a reference, which is currently illegal [7]. Let us +consider what the constructor's parameters would have to be in +order to allow "pair" to hold non-reference types, +references, and constant references:

+ + + + + + + + + + + + + + + + + + +
Type of "T1"Type of parameter to + initializing constructor
T
+
const T &
+
T &
+
T &
+
const T &
+
const T &
+
+ +

A little familiarity with the type traits classes allows us to +construct a single mapping that allows us to determine the type +of parameter from the type of the contained class. The type +traits classes provide a transformation "add_reference", +which adds a reference to its type, unless it is already a +reference.

+ + + + + + + + + + + + + + + + + + + + + + +
Type of "T1"Type of "const T1"Type of "add_reference<const + T1>::type"
T
+
const T
+
const T &
+
T &
+
T & [8]
+
T &
+
const T &
+
const T &
+
const T &
+
+ +

This allows us to build a primary template definition for +"pair" that can contain non-reference types, reference +types, and constant reference types:

+ +
template <typename T1, typename T2> 
+struct pair 
+{
+  typedef T1 first_type;
+  typedef T2 second_type;
+
+  T1 first;
+  T2 second;
+
+  pair(boost::add_reference<const T1>::type nfirst,
+       boost::add_reference<const T2>::type nsecond)
+  :first(nfirst), second(nsecond) { }
+};
+ +

Add back in the standard comparision operators, default +constructor, and template copy constructor (which are all the +same), and you have a std::pair that can hold reference types!

+ +

This same extension could have been done using partial +template specialization of "pair", but to specialize +"pair" in this way would require three partial +specializations, plus the primary template. Type traits allows us +to define a single primary template that adjusts itself auto-magically +to any of these partial specializations, instead of a brute-force +partial specialization approach. Using type traits in this +fashion allows programmers to delegate partial specialization to +the type traits classes, resulting in code that is easier to +maintain and easier to understand.

+ +

Conclusion

+ +

We hope that in this article we have been able to give you +some idea of what type-traits are all about. A more complete +listing of the available classes are in the boost documentation, +along with further examples using type traits. Templates have +enabled C++ uses to take the advantage of the code reuse that +generic programming brings; hopefully this article has shown that +generic programming does not have to sink to the lowest common +denominator, and that templates can be optimal as well as generic.

+ +

Acknowledgements

+ +

The authors would like to thank Beman Dawes and Howard Hinnant +for their helpful comments when preparing this article.

+ +

References

+ +
    +
  1. Nathan C. Myers, C++ Report, June 1995.
  2. +
  3. The type traits library is based upon contributions by + Steve Cleary, Beman Dawes, Howard Hinnant and John + Maddock: it can be found at www.boost.org.
  4. +
  5. A scalar type is an arithmetic type (i.e. a built-in + integer or floating point type), an enumeration type, a + pointer, a pointer to member, or a const- or volatile-qualified + version of one of these types.
  6. +
  7. This quote is from Donald Knuth, ACM Computing Surveys, + December 1974, pg 268.
  8. +
  9. The test code is available as part of the boost utility + library (see algo_opt_examples.cpp), the code was + compiled with gcc 2.95 with all optimisations turned on, + tests were conducted on a 400MHz Pentium II machine + running Microsoft Windows 98.
  10. +
  11. John Maddock and Howard Hinnant have submitted a "compressed_pair" + library to Boost, which uses a technique similar to the + one described here to hold references. Their pair also + uses type traits to determine if any of the types are + empty, and will derive instead of contain to conserve + space -- hence the name "compressed".
  12. +
  13. This is actually an issue with the C++ Core Language + Working Group (issue #106), submitted by Bjarne + Stroustrup. The tentative resolution is to allow a "reference + to a reference to T" to mean the same thing as a + "reference to T", but only in template + instantiation, in a method similar to multiple cv-qualifiers.
  14. +
  15. For those of you who are wondering why this shouldn't be + const-qualified, remember that references are always + implicitly constant (for example, you can't re-assign a + reference). Remember also that "const T &" + is something completely different. For this reason, cv-qualifiers + on template type arguments that are references are + ignored.
  16. +
+ +

Listing 1

+ +
namespace detail{
+
+template <bool b>
+struct copier
+{
+   template<typename I1, typename I2>
+   static I2 do_copy(I1 first, 
+                     I1 last, I2 out);
+};
+
+template <bool b>
+template<typename I1, typename I2>
+I2 copier<b>::do_copy(I1 first, 
+                      I1 last, 
+                      I2 out)
+{
+   while(first != last)
+   {
+      *out = *first;
+      ++out;
+      ++first;
+   }
+   return out;
+}
+
+template <>
+struct copier<true>
+{
+   template<typename I1, typename I2>
+   static I2* do_copy(I1* first, I1* last, I2* out)
+   {
+      memcpy(out, first, (last-first)*sizeof(I2));
+      return out+(last-first);
+   }
+};
+
+}
+
+template<typename I1, typename I2>
+inline I2 copy(I1 first, I1 last, I2 out)
+{
+   typedef typename 
+    boost::remove_cv<
+     typename std::iterator_traits<I1>
+      ::value_type>::type v1_t;
+
+   typedef typename 
+    boost::remove_cv<
+     typename std::iterator_traits<I2>
+      ::value_type>::type v2_t;
+
+   enum{ can_opt = 
+      boost::is_same<v1_t, v2_t>::value
+      && boost::is_pointer<I1>::value
+      && boost::is_pointer<I2>::value
+      && boost::
+      has_trivial_assign<v1_t>::value 
+   };
+
+   return detail::copier<can_opt>::
+      do_copy(first, last, out);
+}
+ +
+ +

© Copyright John Maddock and Steve Cleary, 2000

+ + diff --git a/development/include/boost/type_traits/ice.hpp b/development/include/boost/type_traits/ice.hpp index 1cd5ceb..e2f72d5 100644 --- a/development/include/boost/type_traits/ice.hpp +++ b/development/include/boost/type_traits/ice.hpp @@ -1,5 +1,5 @@ -// (C) Copyright John Maddock 2000. +// (C) Copyright John Maddock and Steve Cleary 2000. // Permission to copy, use, modify, sell and // distribute this software is granted provided this copyright notice appears // in all copies. This software is provided "as is" without express or implied @@ -73,3 +73,4 @@ struct ice_and + diff --git a/development/include/boost/type_traits/same_traits.hpp b/development/include/boost/type_traits/same_traits.hpp index 2a95465..e94f46a 100644 --- a/development/include/boost/type_traits/same_traits.hpp +++ b/development/include/boost/type_traits/same_traits.hpp @@ -1,4 +1,4 @@ -// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// (C) Copyright Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant & John Maddock 2000. // Permission to copy, use, modify, sell and // distribute this software is granted provided this copyright notice appears // in all copies. This software is provided "as is" without express or implied @@ -87,3 +87,4 @@ public: #endif // SAME_TRAITS_HPP + diff --git a/development/include/boost/type_traits/transform_traits.hpp b/development/include/boost/type_traits/transform_traits.hpp index b9d487c..e82f40f 100644 --- a/development/include/boost/type_traits/transform_traits.hpp +++ b/development/include/boost/type_traits/transform_traits.hpp @@ -175,6 +175,8 @@ public: // include a bunch of full specialisations as a workaround: // #include +#else +#define BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(x) #endif #endif // TRANSFORM_TRAITS_HPP @@ -182,3 +184,4 @@ public: + diff --git a/development/include/boost/type_traits/transform_traits_spec.hpp b/development/include/boost/type_traits/transform_traits_spec.hpp index 8d9560d..3d05115 100644 --- a/development/include/boost/type_traits/transform_traits_spec.hpp +++ b/development/include/boost/type_traits/transform_traits_spec.hpp @@ -5,6 +5,9 @@ // This software is provided "as is" without express or implied warranty, // and with no claim as to its suitability for any purpose. +#ifndef BOOST_TT_TRANSFORM_TRAITS_SPEC_HPP +#define BOOST_TT_TRANSFORM_TRAITS_SPEC_HPP + #ifndef TRANSFORM_TRAITS_HPP #include #endif @@ -67,9 +70,5 @@ BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(float) BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(double) BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(long double) -#undef BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_CONST_VOLATILE_RANK1 -#undef BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_1 -#undef BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_2 -#undef BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1 -#undef BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2 +#endif // BOOST_TT_TRANSFORM_TRAITS_SPEC_HPP diff --git a/development/index.htm b/development/index.htm index 7dc6d14..54b5b0e 100644 --- a/development/index.htm +++ b/development/index.htm @@ -5,7 +5,7 @@ content="text/html; charset=iso-8859-1"> - + Type Traits @@ -471,8 +471,8 @@ relationship between two types:

8.5

Note that - this template is currently broken with Borland's compiler, - for constructor-based conversions. + this template is currently broken with Borland's + compiler, for constructor-based conversions.   @@ -595,7 +595,64 @@ transformation to the template argument T:

-

 

+

As the table above indicates, support for partial +specialization of class templates is required to correctly +implement the type transformation templates. On the other hand, +practice shows that many of the templates from this category are +very useful, and often essential for implementing some generic +libraries. Lack of these templates is often one of the major +limiting factors in porting those libraries to compilers that do +not yet support this language feature. As some of these compilers +are going to be around for a while, and at least one of them is +very wide-spread, it was decided that the library should provide +workarounds where possible. The basic idea behind the workaround +is

+ +
    +
  1. To manually define full specializations of all type + transformation templates for all fundamental types, and + all their 1st and 2nd rank cv-[un]qualified derivative + pointer types, and to
  2. +
  3. Provide a user-level macro that will define such explicit + specializations for any user-defined type T.
  4. +
+ +

The first part guarantees the successful compilation of +something like this:

+ +
BOOST_STATIC_ASSERT((is_same<char, remove_reference<char&>::type>::value));
+ +
BOOST_STATIC_ASSERT((is_same<char const, remove_reference<char const&>::type>::value));
+ +
BOOST_STATIC_ASSERT((is_same<char volatile, remove_reference<char volatile&>::type>::value));
+ +
BOOST_STATIC_ASSERT((is_same<char const volatile, remove_reference<char const volatile&>::type>::value));
+ +
BOOST_STATIC_ASSERT((is_same<char*, remove_reference<char*&>::type>::value));
+ +
BOOST_STATIC_ASSERT((is_same<char const*, remove_reference<char const*&>::type>::value));
+ +
...
+ +
BOOST_STATIC_ASSERT((is_same<char const volatile* const volatile* const volatile, remove_reference<char const volatile* const volatile* const volatile&>::type>::value));
+ +

and the second part provides library's users with a mechanism +to make the above code work not only for 'char', 'int' or other +built-in type, but for they own types too:

+ +
struct my {};
+ +
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(my)
+ +
BOOST_STATIC_ASSERT((is_same<my, remove_reference<my&>::type>::value));
+ +
BOOST_STATIC_ASSERT((is_same<my, remove_const<my const>::type>::value));
+ +
// etc.
+ +

Note that the maco +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION evaluates to +nothing on those compilers that do support partial specialisation.

Compiler Support Information

@@ -637,11 +694,11 @@ happen if: T is a union or T is a compiler-supplied scalar type that is not specialised for in these type traits.

If there is no compiler support, to ensure that these -traits always return the correct values, specialise 'is_union' -for each user-defined union type, 'is_empty' for each user-defined -empty composite type, and 'is_POD' for each user-defined POD type. -The 'has_*' traits should also be specialized if the user-defined -type has those traits and is not a POD.

+traits always return the correct values, specialise +'is_union' for each user-defined union type, 'is_empty' for each +user-defined empty composite type, and 'is_POD' for each user-defined +POD type. The 'has_*' traits should also be specialized if the +user-defined type has those traits and is not a POD.

The following rules are automatically enforced:

diff --git a/examples/copy_example.cpp b/examples/copy_example.cpp new file mode 100644 index 0000000..c20e27a --- /dev/null +++ b/examples/copy_example.cpp @@ -0,0 +1,240 @@ + +/* + * + * Copyright (c) 1999 + * Dr John Maddock + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Dr John Maddock makes no representations + * about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + * This file provides some example of type_traits usage - + * by "optimising" various algorithms: + * + * opt::copy - optimised for trivial copy (cf std::copy) + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +using std::cout; +using std::endl; +using std::cin; + +namespace opt{ + +// +// opt::copy +// same semantics as std::copy +// calls memcpy where appropiate. +// + +namespace detail{ + +template +I2 copy_imp(I1 first, I1 last, I2 out) +{ + while(first != last) + { + *out = *first; + ++out; + ++first; + } + return out; +} + +template +struct copier +{ + template + static I2 do_copy(I1 first, I1 last, I2 out) + { return copy_imp(first, last, out); } +}; + +template <> +struct copier +{ + template + static I2* do_copy(I1* first, I1* last, I2* out) + { + memcpy(out, first, (last-first)*sizeof(I2)); + return out+(last-first); + } +}; + + +} + +#ifndef BOOST_NO_STD_ITERATOR_TRAITS + +template +inline I2 copy(I1 first, I1 last, I2 out) +{ + typedef typename boost::remove_cv::value_type>::type v1_t; + typedef typename boost::remove_cv::value_type>::type v2_t; + return detail::copier< + ::boost::type_traits::ice_and< + ::boost::is_same::value, + ::boost::is_pointer::value, + ::boost::is_pointer::value, + ::boost::has_trivial_assign::value + >::value>::do_copy(first, last, out); +} + +#else // BOOST_NO_STD_ITERATOR_TRAITS + +// +// If there is no standard iterator_traits then we have to +// use overloading rather than iterator_traits to detect +// when we have T*'s to copy. Note that we cannot overload +// copy directly as that will cause some standard conforming +// code to fail to build: + +namespace detail{ + +template +inline I2 copy_(const I1& first, const I1& last, const I2& out) +{ + return detail::copier::do_copy(first, last, out); +} + +template +inline T* copy_(const T* first, const T* last, T* out) +{ + return detail::copier< + ::boost::has_trivial_assign::value + >::do_copy(first, last, out); +} + +} // namespace detail + +template +inline I2 copy(I1 first, I1 last, I2 out) +{ + return detail::copy_(first, last, out); +} + +#endif // BOOST_NO_STD_ITERATOR_TRAITS + +}; // namespace opt + +// +// define some global data: +// +const int array_size = 1000; +int i_array_[array_size] = {0,}; +const int ci_array_[array_size] = {0,}; +char c_array_[array_size] = {0,}; +const char cc_array_[array_size] = { 0,}; +// +// since arrays aren't iterators we define a set of pointer +// aliases into the arrays (otherwise the compiler is entitled +// to deduce the type passed to the template functions as +// T (&)[N] rather than T*). +int* i_array = i_array_; +const int* ci_array = ci_array_; +char* c_array = c_array_; +const char* cc_array = cc_array_; + +const int iter_count = 1000000; + +int main() +{ + boost::timer t; + double result; + int i; + cout << "Measuring times in micro-seconds per 1000 elements processed" << endl << endl; + cout << "testing copy...\n" + "[Some standard library versions may already perform this optimisation.]" << endl; + + // cache load: + opt::copy(ci_array, ci_array + array_size, i_array); + + // time optimised version: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::copy(ci_array, ci_array + array_size, i_array); + } + result = t.elapsed(); + cout << "opt::copy: " << result << endl; + + // cache load: + std::copy(ci_array, ci_array + array_size, i_array); + + // time standard version: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + std::copy(ci_array, ci_array + array_size, i_array); + } + result = t.elapsed(); + cout << "std::copy: " << result << endl; + + // cache load: + opt::detail::copier::do_copy(ci_array, ci_array + array_size, i_array); + + // time unoptimised version: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::detail::copier::do_copy(ci_array, ci_array + array_size, i_array); + } + result = t.elapsed(); + cout << "standard \"unoptimised\" copy: " << result << endl << endl; + + // cache load: + opt::copy(cc_array, cc_array + array_size, c_array); + + // time optimised version: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::copy(cc_array, cc_array + array_size, c_array); + } + result = t.elapsed(); + cout << "opt::copy: " << result << endl; + + // cache load: + std::copy(cc_array, cc_array + array_size, c_array); + + // time standard version: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + std::copy(cc_array, cc_array + array_size, c_array); + } + result = t.elapsed(); + cout << "std::copy: " << result << endl; + + // cache load: + opt::detail::copier::do_copy(cc_array, cc_array + array_size, c_array); + + // time unoptimised version: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::detail::copier::do_copy(cc_array, cc_array + array_size, c_array); + } + result = t.elapsed(); + cout << "standard \"unoptimised\" copy: " << result << endl << endl; + + return 0; +} + + + + + + diff --git a/examples/fill_example.cpp b/examples/fill_example.cpp new file mode 100644 index 0000000..ce5f03e --- /dev/null +++ b/examples/fill_example.cpp @@ -0,0 +1,191 @@ + +/* + * + * Copyright (c) 1999 + * Dr John Maddock + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Dr John Maddock makes no representations + * about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + * This file provides some example of type_traits usage - + * by "optimising" various algorithms: + * + * opt::fill - optimised for trivial copy/small types (cf std::fill) + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#if defined(BOOST_NO_STDC_NAMESPACE) || (defined(std) && defined(__SGI_STL_PORT)) +namespace std{ using :: memset; } +#endif + +using std::cout; +using std::endl; +using std::cin; + +namespace opt{ +// +// fill +// same as std::fill, uses memset where appropriate, along with call_traits +// to "optimise" parameter passing. +// +namespace detail{ + +template +void do_fill_(I first, I last, typename boost::call_traits::param_type val) +{ + while(first != last) + { + *first = val; + ++first; + } +} + +template +struct filler +{ + template + struct rebind + { + static void do_fill(I first, I last, typename boost::call_traits::param_type val) + { do_fill_(first, last, val); } + }; +}; + +template <> +struct filler +{ + template + struct rebind + { + static void do_fill(I first, I last, T val) + { + std::memset(first, val, last-first); + } + }; +}; + +} + +template +inline void fill(I first, I last, const T& val) +{ + typedef detail::filler< + ::boost::type_traits::ice_and< + ::boost::is_pointer::value, + ::boost::is_arithmetic::value, + (sizeof(T) == 1) + >::value> filler_t; + typedef typename filler_t:: template rebind binder; + binder::do_fill(first, last, val); +} + +}; // namespace opt + +// +// define some global data: +// +const int array_size = 1000; +int i_array_[array_size] = {0,}; +const int ci_array_[array_size] = {0,}; +char c_array_[array_size] = {0,}; +const char cc_array_[array_size] = { 0,}; +// +// since arrays aren't iterators we define a set of pointer +// aliases into the arrays (otherwise the compiler is entitled +// to deduce the type passed to the template functions as +// T (&)[N] rather than T*). +int* i_array = i_array_; +const int* ci_array = ci_array_; +char* c_array = c_array_; +const char* cc_array = cc_array_; + +const int iter_count = 1000000; + +int main() +{ + boost::timer t; + double result; + int i; + // + // test destroy_array, + // compare destruction time of an array of ints + // with unoptimised form. + // + cout << "Measuring times in micro-seconds per 1000 elements processed" << endl << endl; + + cout << "testing fill(char)...\n" + "[Some standard library versions may already perform this optimisation.]" << endl; + + // cache load: + opt::fill(c_array, c_array + array_size, (char)3); + + // time optimised version: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::fill(c_array, c_array + array_size, (char)3); + } + result = t.elapsed(); + cout << "opt::fill: " << result << endl; + + // cache load: + std::fill(c_array, c_array + array_size, (char)3); + + // time standard version: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + std::fill(c_array, c_array + array_size, (char)3); + } + result = t.elapsed(); + cout << "std::fill: " << result << endl << endl; + + cout << "testing fill(int)...\n" + "[Tests the effect of call_traits pass-by-value optimisation -\nthe value of this optimisation may depend upon hardware characteristics.]" << endl; + + // cache load: + opt::fill(i_array, i_array + array_size, 3); + + // timer optimised version: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::fill(i_array, i_array + array_size, 3); + } + result = t.elapsed(); + cout << "opt::fill: " << result << endl; + + // cache load: + std::fill(i_array, i_array + array_size, 3); + + // time standard version: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + std::fill(i_array, i_array + array_size, 3); + } + result = t.elapsed(); + cout << "std::fill: " << result << endl << endl; + + return 0; +} + + + + + diff --git a/examples/iter_swap_example.cpp b/examples/iter_swap_example.cpp new file mode 100644 index 0000000..898d0bd --- /dev/null +++ b/examples/iter_swap_example.cpp @@ -0,0 +1,110 @@ + +/* + * + * Copyright (c) 1999 + * Dr John Maddock + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Dr John Maddock makes no representations + * about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + * This file provides some example of type_traits usage - + * by "optimising" various algorithms: + * + * opt::iter_swap - uses type_traits to determine whether the iterator is a proxy + * in which case it uses a "safe" approach, otherwise calls swap + * on the assumption that swap may be specialised for the pointed-to type. + * + */ + +#include +#include +#include +#include +#include +#include + +#include + +using std::cout; +using std::endl; +using std::cin; + +namespace opt{ + +// +// iter_swap: +// tests whether iterator is a proxying iterator or not, and +// uses optimal form accordingly: +// +namespace detail{ + +template +struct swapper +{ + template + static void do_swap(I one, I two) + { + typedef typename std::iterator_traits::value_type v_t; + v_t v = *one; + *one = *two; + *two = v; + } +}; + +#ifdef __GNUC__ +using std::swap; +#endif + +template <> +struct swapper +{ + template + static void do_swap(I one, I two) + { + using std::swap; + swap(*one, *two); + } +}; + +} + +template +inline void iter_swap(I1 one, I2 two) +{ + typedef typename std::iterator_traits::reference r1_t; + typedef typename std::iterator_traits::reference r2_t; + detail::swapper< + ::boost::type_traits::ice_and< + ::boost::is_reference::value, + ::boost::is_reference::value, + ::boost::is_same::value + >::value>::do_swap(one, two); +} + + +}; // namespace opt + +int main() +{ + // + // testing iter_swap + // really just a check that it does in fact compile... + std::vector v1; + v1.push_back(0); + v1.push_back(1); + std::vector v2; + v2.push_back(0); + v2.push_back(1); + opt::iter_swap(v1.begin(), v1.begin()+1); + opt::iter_swap(v2.begin(), v2.begin()+1); + + cout << "Press any key to exit..."; + cin.get(); +} + + diff --git a/examples/trivial_destructor_example.cpp b/examples/trivial_destructor_example.cpp new file mode 100644 index 0000000..ff7d256 --- /dev/null +++ b/examples/trivial_destructor_example.cpp @@ -0,0 +1,166 @@ + +/* + * + * Copyright (c) 1999 + * Dr John Maddock + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Dr John Maddock makes no representations + * about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + * This file provides some example of type_traits usage - + * by "optimising" various algorithms: + * + * opt::destroy_array - an example of optimisation based upon omitted destructor calls + * + */ + + +#include + +#include +#include + +using std::cout; +using std::endl; +using std::cin; + +namespace opt{ + +// +// algorithm destroy_array: +// The reverse of std::unitialized_copy, takes a block of +// initialized memory and calls destructors on all objects therein. +// + +namespace detail{ + +template +struct array_destroyer +{ + template + static void destroy_array(T* i, T* j){ do_destroy_array(i, j); } +}; + +template <> +struct array_destroyer +{ + template + static void destroy_array(T*, T*){} +}; + +template +void do_destroy_array(T* first, T* last) +{ + while(first != last) + { + first->~T(); + ++first; + } +} + +}; // namespace detail + +template +inline void destroy_array(T* p1, T* p2) +{ + detail::array_destroyer::value>::destroy_array(p1, p2); +} + +// +// unoptimised versions of destroy_array: +// +template +void destroy_array1(T* first, T* last) +{ + while(first != last) + { + first->~T(); + ++first; + } +} +template +void destroy_array2(T* first, T* last) +{ + for(; first != last; ++first) first->~T(); +} + +} // namespace opt + +// +// define some global data: +// +const int array_size = 1000; +int i_array[array_size] = {0,}; +const int ci_array[array_size] = {0,}; +char c_array[array_size] = {0,}; +const char cc_array[array_size] = { 0,}; + +const int iter_count = 1000000; + + +int main() +{ + boost::timer t; + double result; + int i; + // + // test destroy_array, + // compare destruction time of an array of ints + // with unoptimised form. + // + cout << "Measuring times in micro-seconds per 1000 elements processed" << endl << endl; + cout << "testing destroy_array...\n" + "[Some compilers may be able to optimise the \"unoptimised\"\n versions as well as type_traits does.]" << endl; + + // cache load: + opt::destroy_array(i_array, i_array + array_size); + + // time optimised version: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::destroy_array(i_array, i_array + array_size); + } + result = t.elapsed(); + cout << "destroy_array: " << result << endl; + + // cache load: + opt::destroy_array1(i_array, i_array + array_size); + + // time unoptimised version #1: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::destroy_array1(i_array, i_array + array_size); + } + result = t.elapsed(); + cout << "destroy_array(unoptimised#1): " << result << endl; + + // cache load: + opt::destroy_array2(i_array, i_array + array_size); + + // time unoptimised version #2: + t.restart(); + for(i = 0; i < iter_count; ++i) + { + opt::destroy_array2(i_array, i_array + array_size); + } + result = t.elapsed(); + cout << "destroy_array(unoptimised#2): " << result << endl << endl; + + return 0; +} + + + + + + + + + diff --git a/include/boost/type_traits.hpp b/include/boost/type_traits.hpp index b177a4e..04dcc68 100644 --- a/include/boost/type_traits.hpp +++ b/include/boost/type_traits.hpp @@ -10,14 +10,33 @@ #ifndef BOOST_TYPE_TRAITS_HPP #define BOOST_TYPE_TRAITS_HPP -#ifndef BOOST_CONFIG_HPP -#include -#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#include -#else -#include -#endif +/**************************************************************************/ + +// +// undefine helper macro's: +// +#undef BOOST_IS_CLASS +#undef BOOST_IS_ENUM +#undef BOOST_IS_UNION +#undef BOOST_IS_POD +#undef BOOST_IS_EMPTY +#undef BOOST_HAS_TRIVIAL_CONSTRUCTOR +#undef BOOST_HAS_TRIVIAL_COPY +#undef BOOST_HAS_TRIVIAL_ASSIGN +#undef BOOST_HAS_TRIVIAL_DESTRUCTOR #endif // BOOST_TYPE_TRAITS_HPP + + + diff --git a/include/boost/type_traits/alignment_traits.hpp b/include/boost/type_traits/alignment_traits.hpp new file mode 100644 index 0000000..7de0c30 --- /dev/null +++ b/include/boost/type_traits/alignment_traits.hpp @@ -0,0 +1,82 @@ + +// (C) Copyright John Maddock 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// +// defines alignment_of: + +#ifndef ALIGNMENT_TYPE_TRAITS_HPP +#define ALIGNMENT_TYPE_TRAITS_HPP + +#include +#ifndef BOOST_ICE_TYPE_TRAITS_HPP +#include +#endif + +namespace boost{ +// +// get the alignment of some arbitrary type: +namespace detail{ + +template +struct alignment_of_hack +{ + char c; + T t; + alignment_of_hack(); +}; + +template +struct alignment_logic +{ + BOOST_DECL_MC(std::size_t, value, A < S ? A : S); +}; + +} // namespace detail + +template +struct alignment_of +{ + BOOST_DECL_MC(std::size_t, value, + (::boost::detail::alignment_logic< + sizeof(detail::alignment_of_hack) - sizeof(T), + sizeof(T) + >::value)); +}; + +// +// references have to be treated specially, assume +// that a reference is just a special pointer: +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct alignment_of +{ +public: + BOOST_DECL_MC(std::size_t, value, alignment_of::value); +}; +#endif +// +// void has to be treated specially: +template <> +struct alignment_of +{ BOOST_DECL_MC(std::size_t, value, 0); }; +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS +template <> +struct alignment_of +{ BOOST_DECL_MC(std::size_t, value, 0); }; +template <> +struct alignment_of +{ BOOST_DECL_MC(std::size_t, value, 0); }; +template <> +struct alignment_of +{ BOOST_DECL_MC(std::size_t, value, 0); }; +#endif + +} // namespace boost + +#endif // ALIGNMENT_TYPE_TRAITS_HPP + + diff --git a/include/boost/type_traits/arithmetic_traits.hpp b/include/boost/type_traits/arithmetic_traits.hpp new file mode 100644 index 0000000..abd4cd9 --- /dev/null +++ b/include/boost/type_traits/arithmetic_traits.hpp @@ -0,0 +1,262 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// +// defines traits classes for arithmetic types: +// is_void, is_integral, is_float, is_arithmetic, is_fundamental. +// + + +#ifndef ARITHMETIC_TYPE_TRAITS_HPP +#define ARITHMETIC_TYPE_TRAITS_HPP + +#ifndef BOOST_ICE_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_FWD_TYPE_TRAITS_HPP +#include +#endif + +namespace boost{ + +//* is a type T void - is_void +template struct is_void{ BOOST_DECL_MC(bool, value, false); }; +template <> struct is_void{ BOOST_DECL_MC(bool, value, true); }; + +//* is a type T an integral type described in the standard (3.9.1p3) +template struct is_integral +{ BOOST_DECL_MC(bool, value, false); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#ifndef BOOST_MSVC +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#endif +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; + +#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#endif +#if defined(__BORLANDC__) || defined(_MSC_VER) && !defined(__MWERKS__) +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral<__int64> +{ BOOST_DECL_MC(bool, value, true); }; +#endif + +//* is a type T a floating-point type described in the standard (3.9.1p8) +template struct is_float +{ BOOST_DECL_MC(bool, value, false); }; +template <> struct is_float +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_float +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_float +{ BOOST_DECL_MC(bool, value, true); }; + +// +// declare cv-qualified specialisations of these templates only +// if BOOST_NO_CV_SPECIALIZATIONS is not defined: +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS +template <> struct is_void +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_void +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_void +{ BOOST_DECL_MC(bool, value, true); }; +#endif +#ifndef BOOST_NO_CV_SPECIALIZATIONS +// const-variations: +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#ifndef BOOST_MSVC +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#endif +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; + +#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#endif // ULLONG_MAX +#if defined(__BORLANDC__) || defined(_MSC_VER) && !defined(__MWERKS__) +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#endif //__int64 + +template <> struct is_float +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_float +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_float +{ BOOST_DECL_MC(bool, value, true); }; + +// volatile-variations: +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#ifndef BOOST_MSVC +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#endif +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; + +#ifdef ULLONG_MAX +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#endif // ULLONG_MAX +#if defined(__BORLANDC__) || defined(_MSC_VER) && !defined(__MWERKS__) +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#endif //__int64 + +template <> struct is_float +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_float +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_float +{ BOOST_DECL_MC(bool, value, true); }; + +// const-volatile-variations: +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#ifndef BOOST_MSVC +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#endif +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; + +#ifdef ULLONG_MAX +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#endif // ULLONG_MAX +#if defined(__BORLANDC__) || defined(_MSC_VER) && !defined(__MWERKS__) +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_integral +{ BOOST_DECL_MC(bool, value, true); }; +#endif //__int64 + +template <> struct is_float +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_float +{ BOOST_DECL_MC(bool, value, true); }; +template <> struct is_float +{ BOOST_DECL_MC(bool, value, true); }; + +#endif // BOOST_NO_CV_SPECIALIZATIONS + +//* is a type T an arithmetic type described in the standard (3.9.1p8) +template +struct is_arithmetic +{ + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_or< + ::boost::is_integral::value, + ::boost::is_float::value + >::value)); +}; + +//* is a type T a fundamental type described in the standard (3.9.1) +template +struct is_fundamental +{ + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_or< + ::boost::is_arithmetic::value, + ::boost::is_void::value + >::value)); +}; + +} // namespace boost + +#endif + + + + + diff --git a/include/boost/type_traits/composite_traits.hpp b/include/boost/type_traits/composite_traits.hpp new file mode 100644 index 0000000..fd7b62d --- /dev/null +++ b/include/boost/type_traits/composite_traits.hpp @@ -0,0 +1,357 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// +// defines traits classes for composite types: +// is_array, is_pointer, is_reference, is_member_pointer, is_enum, is_union. +// +// Some workarounds in here use ideas suggested from "Generic: +// Mappings between Types and Values" +// by Andrei Alexandrescu (see http://www.cuj.com/experts/1810/alexandr.html). +// Mat Marcus and Jesse Jones posted a version of is_pointer very similar to this one +// on the boost list (Copyright 2000 Adobe Systems Incorporated and others. +// All rights reserved.). +// Fixes for is_array are based on a newgroup posting by Jonathan Lundquist. + +#ifndef COMPOSITE_TYPE_TRAITS_HPP +#define COMPOSITE_TYPE_TRAITS_HPP + +#ifndef BOOST_ICE_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_FWD_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_CONVERSION_TYPE_TRAITS_HPP +#include +#endif +#ifndef CV_TYPE_TRAITS_HPP +#include +#endif +#ifndef ARITHMETIC_TYPE_TRAITS_HPP +#include +#endif + +namespace boost{ + +/********************************************** + * + * is_array + * + **********************************************/ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template struct is_array +{ BOOST_DECL_MC(bool, value, false); }; +template struct is_array +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_array +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_array +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_array +{ BOOST_DECL_MC(bool, value, true); }; +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace detail{ + struct pointer_helper + { + pointer_helper(const volatile void*); + }; + yes_type is_pointer_helper(pointer_helper); + no_type is_pointer_helper(...); + template + yes_type is_pointer_helper3(T (*)(void)); + template + yes_type is_pointer_helper3(T (*)(A1)); + template + yes_type is_pointer_helper3(T (*)(A1, A2)); + template + yes_type is_pointer_helper3(T (*)(A1, A2, A3)); + no_type is_pointer_helper3(...); + + yes_type is_array_helper(const volatile void*, const volatile void*); + template + no_type is_array_helper(T*const volatile*, const volatile void*); + no_type is_array_helper(...); +} // namespace detail +template +struct is_array +{ +private: + static T t; +public: + BOOST_DECL_MC(bool, value, (1 == sizeof(detail::is_array_helper(&t, t))) + & !is_reference::value + & !(1 == sizeof(detail::is_pointer_helper3(t))) ); +}; +template <> +struct is_array +{ + BOOST_DECL_MC(bool, value, false); +}; +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS +template <> +struct is_array +{ + BOOST_DECL_MC(bool, value, false); +}; +template <> +struct is_array +{ + BOOST_DECL_MC(bool, value, false); +}; +template <> +struct is_array +{ + BOOST_DECL_MC(bool, value, false); +}; +#endif + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +/********************************************** + * + * is_pointer + * + **********************************************/ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace detail{ +template struct is_pointer_helper +{ BOOST_DECL_MC(bool, value, false); }; +template struct is_pointer_helper +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_pointer_helper +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_pointer_helper +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_pointer_helper +{ BOOST_DECL_MC(bool, value, true); }; +} // namespace detail +template struct is_pointer +{ BOOST_DECL_MC(bool, value, (::boost::type_traits::ice_and< ::boost::detail::is_pointer_helper::value, !::boost::is_member_pointer::value>::value)); }; +#else +template +struct is_pointer +{ +private: + static T t; +public: + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_and< + !::boost::is_reference::value, + !::boost::is_array::value, + (::boost::type_traits::ice_or< + (1 == sizeof(detail::is_pointer_helper(t))), + (1 == sizeof(detail::is_pointer_helper3(t))) + >::value) + >::value ) ); +}; +template <> +struct is_pointer +{ + BOOST_DECL_MC(bool, value, false); +}; +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS +template <> +struct is_pointer +{ + BOOST_DECL_MC(bool, value, false); +}; +template <> +struct is_pointer +{ + BOOST_DECL_MC(bool, value, false); +}; +template <> +struct is_pointer +{ + BOOST_DECL_MC(bool, value, false); +}; +#endif +#endif + +/********************************************** + * + * is_reference + * + **********************************************/ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template struct is_reference +{ BOOST_DECL_MC(bool, value, false); }; +template struct is_reference +{ BOOST_DECL_MC(bool, value, true); }; +#if defined(__BORLANDC__) +// these are illegal specialisations; cv-qualifies applied to +// references have no effect according to [8.3.2p1], +// C++ Builder requires them though as it treats cv-qualified +// references as distinct types... +template struct is_reference +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_reference +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_reference +{ BOOST_DECL_MC(bool, value, true); }; +#endif +#else +# ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable: 4181) +# endif // BOOST_MSVC +template struct is_reference +{ +private: + typedef T const volatile cv_t; +public: + BOOST_DECL_MC(bool, value, (::boost::type_traits::ice_or::value, !::boost::is_volatile::value>::value)); +}; +template <> struct is_reference +{ + BOOST_DECL_MC(bool, value, false); +}; +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS +template <> struct is_reference +{ BOOST_DECL_MC(bool, value, false); }; +template <> struct is_reference +{ BOOST_DECL_MC(bool, value, false); }; +template <> struct is_reference +{ BOOST_DECL_MC(bool, value, false); }; +#endif + +# ifdef BOOST_MSVC +# pragma warning(pop) +# endif // BOOST_MSVC +#endif + +/********************************************** + * + * is_union + * + **********************************************/ +template struct is_union +{ +private: + typedef typename remove_cv::type cvt; +public: + BOOST_DECL_MC(bool, value, BOOST_IS_UNION(cvt)); +}; + +/********************************************** + * + * is_enum + * + **********************************************/ +namespace detail{ +struct int_convertible +{ + int_convertible(int); +}; +} // namespace detail +#ifndef __BORLANDC__ +template struct is_enum +{ + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_and< + !::boost::is_arithmetic::value, + !::boost::is_reference::value, + ::boost::is_convertible::value + >::value)); +}; +#else // __BORLANDC__ +// +// buggy is_convertible prevents working +// implementation of is_enum: +template struct is_enum +{ +public: + BOOST_DECL_MC(bool, value, BOOST_IS_ENUM(T)); +}; +#endif + +/********************************************** + * + * is_member_pointer + * + **********************************************/ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template struct is_member_pointer +{ BOOST_DECL_MC(bool, value, false); }; +template struct is_member_pointer +{ BOOST_DECL_MC(bool, value, true); }; +#ifdef __GNUC__ +// gcc workaround (JM 02 Oct 2000) +template struct is_member_pointer +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_member_pointer +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_member_pointer +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_member_pointer +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_member_pointer +{ BOOST_DECL_MC(bool, value, true); }; +template struct is_member_pointer +{ BOOST_DECL_MC(bool, value, true); }; +#endif +#else +namespace detail{ + template + yes_type is_member_pointer_helper(T (U::*)); + template + yes_type is_member_pointer_helper(T (U::*)(void)); + template + yes_type is_member_pointer_helper(T (U::*)(A1)); + template + yes_type is_member_pointer_helper(T (U::*)(A1, A2)); + template + yes_type is_member_pointer_helper(T (U::*)(A1, A2, A3)); + template + yes_type is_member_pointer_helper(T (U::*)(A1, A2, A3, A4)); + template + yes_type is_member_pointer_helper(T (U::*)(A1, A2, A3, A4, A5)); + no_type is_member_pointer_helper(...); +} +template +struct is_member_pointer +{ +private: + static T t; +public: + BOOST_DECL_MC(bool, value, (1 == sizeof(detail::is_member_pointer_helper(t))) ); +}; +template <> +struct is_member_pointer +{ + BOOST_DECL_MC(bool, value, false); +}; +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS +template <> +struct is_member_pointer +{ + BOOST_DECL_MC(bool, value, false); +}; +template <> +struct is_member_pointer +{ + BOOST_DECL_MC(bool, value, false); +}; +template <> +struct is_member_pointer +{ + BOOST_DECL_MC(bool, value, false); +}; +#endif + +#endif + + +} // namespace boost + +#endif // COMPOSITE_TYPE_TRAITS_HPP + + + + + diff --git a/include/boost/type_traits/conversion_traits.hpp b/include/boost/type_traits/conversion_traits.hpp new file mode 100644 index 0000000..dcc2533 --- /dev/null +++ b/include/boost/type_traits/conversion_traits.hpp @@ -0,0 +1,224 @@ + +// Copyright (C) 2000 John Maddock (john_maddock@compuserve.com) +// Copyright (C) 2000 Jeremy Siek (jsiek@lsc.nd.edu) +// Copyright (C) 1999, 2000 Jaakko J„rvi (jaakko.jarvi@cs.utu.fi) +// +// Permission to copy and use this software is granted, +// provided this copyright notice appears in all copies. +// Permission to modify the code and to distribute modified code is granted, +// provided this copyright notice appears in all copies, and a notice +// that the code was modified is included with the copyright notice. +// +// This software is provided "as is" without express or implied warranty, +// and with no claim as to its suitability for any purpose. + +#ifndef BOOST_CONVERSION_TYPE_TRAITS_HPP +#define BOOST_CONVERSION_TYPE_TRAITS_HPP + +#ifndef BOOST_ICE_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_FWD_TYPE_TRAITS_HPP +#include +#endif +#ifndef ARITHMETIC_TYPE_TRAITS_HPP +#include +#endif +// +// is one type convertable to another? +// +// there are multiple versions of the is_convertible +// template, almost every compiler seems to require its +// own version. +// +// Thanks to Andrei Alexandrescu for the original version of the +// conversion detection technique! +// + +namespace boost{ + +#ifdef BOOST_MSVC + +// +// MS specific version: +// +namespace detail{ + + // This workaround is necessary to handle when From is void + // which is normally taken care of by the partial specialization + // of the is_convertible class. + using ::boost::type_traits::yes_type; + using ::boost::type_traits::no_type; + + struct from_not_void_conversion { + template + struct bind { + static no_type check(...); + static yes_type check(To); + public: + void foo(); // avoid warning about all members being private + static From from; + enum { exists = sizeof( check(from) ) == sizeof(yes_type) }; + }; + }; + struct from_is_void_conversion { + template + struct bind { + enum { exists = ::boost::is_void::value }; + }; + }; + + template + struct conversion_helper { + typedef from_not_void_conversion type; + }; + template <> + struct conversion_helper { + typedef from_is_void_conversion type; + }; +} // namespace detail + +template +struct is_convertible +{ + typedef typename detail::conversion_helper::type Selector; + typedef Selector::template bind Conversion; +public: + enum { value = Conversion::exists }; +}; + +#elif defined(__BORLANDC__) +// +// special version for Borland compilers +// this version breaks when used for some +// UDT conversions: +// +template +struct is_convertible_helper +{ +private: + // This workaround for Borland breaks the EDG C++ frontend, + // so we only use it for Borland. + template + struct checker + { + static type_traits::no_type check(...); + static type_traits::yes_type check(T); + }; + static From from; +public: + static const bool value = sizeof( checker::check(from) ) == sizeof(type_traits::yes_type); + + void foo(); // avoid warning about all members being private +}; + +template +struct is_convertible +{ +private: + typedef is_convertible_helper c_type; + enum{ v = c_type::value }; + char force_it[v ? 1 : 2]; +public: + static const bool value = is_convertible_helper::value; +}; + +template +struct is_convertible +{ + static const bool value = false; +}; +template +struct is_convertible +{ + static const bool value = false; +}; +template <> +struct is_convertible +{ + static const bool value = true; +}; + +#elif defined(__GNUC__) +// +// special version for gcc compiler +// +namespace detail{ + struct any_conversion + { + template + any_conversion(const T&); + }; + template + struct checker + { + static boost::type_traits::no_type check(any_conversion ...); + static boost::type_traits::yes_type check(T, int); + }; +} // namespace detail +template +struct is_convertible +{ +private: + static From from; +public: + static const bool value = sizeof( detail::checker::check(from, 0) ) == sizeof(type_traits::yes_type); + + void foo(); // avoid warning about all members being private +}; + +template +struct is_convertible +{ + static const bool value = false; +}; +template +struct is_convertible +{ + static const bool value = false; +}; +template <> +struct is_convertible +{ + static const bool value = true; +}; + +#else + +template +struct is_convertible +{ +private: + static type_traits::no_type check(...); + static type_traits::yes_type check(To); + static From from; +public: + BOOST_DECL_MC(bool, value, sizeof( check(from) ) == sizeof(type_traits::yes_type)); + void foo(); // avoid warning about all members being private +}; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct is_convertible +{ + BOOST_DECL_MC(bool, value, false); +}; + +template +struct is_convertible +{ + BOOST_DECL_MC(bool, value, false); +}; + +template <> +struct is_convertible +{ + BOOST_DECL_MC(bool, value, true); +}; +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#endif // is_convertible + +} // namespace boost + +#endif // include guard diff --git a/include/boost/type_traits/cv_traits.hpp b/include/boost/type_traits/cv_traits.hpp new file mode 100644 index 0000000..fe33530 --- /dev/null +++ b/include/boost/type_traits/cv_traits.hpp @@ -0,0 +1,214 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// +// defines traits classes for cv-qualified types: +// is_const, is_volatile, remove_const, remove_volatile, remove_cv. +// + +#ifndef CV_TYPE_TRAITS_HPP +#define CV_TYPE_TRAITS_HPP + +#ifndef BOOST_ICE_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_FWD_TYPE_TRAITS_HPP +#include +#endif + +namespace boost{ + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace detail{ +// +// implementation helper: +// +template +struct cv_traits_imp{}; + +template +struct cv_traits_imp +{ + BOOST_DECL_MC(bool, is_const, false); + BOOST_DECL_MC(bool, is_volatile, false); + typedef T unqualified_type; +}; + +template +struct cv_traits_imp +{ + BOOST_DECL_MC(bool, is_const, true); + BOOST_DECL_MC(bool, is_volatile, false); + typedef T unqualified_type; +}; + +template +struct cv_traits_imp +{ + BOOST_DECL_MC(bool, is_const, false); + BOOST_DECL_MC(bool, is_volatile, true); + typedef T unqualified_type; +}; + +template +struct cv_traits_imp +{ + BOOST_DECL_MC(bool, is_const, true); + BOOST_DECL_MC(bool, is_volatile, true); + typedef T unqualified_type; +}; + +template +struct remove_const_helper +{ + typedef T type; +}; +template +struct remove_const_helper +{ + typedef volatile T type; +}; + +template +struct remove_volatile_helper +{ + typedef T type; +}; +template +struct remove_volatile_helper +{ + typedef const T type; +}; + +} // namespace detail + +// * convert a type T to a non-volatile type - remove_volatile +template +struct remove_volatile +{ + typedef typename detail::cv_traits_imp::unqualified_type uq_type; + typedef typename detail::remove_volatile_helper::value>::type type; +}; +template struct remove_volatile{ typedef T& type; }; + +// * convert a type T to non-const type - remove_const +template +struct remove_const +{ + typedef typename detail::cv_traits_imp::unqualified_type uq_type; + typedef typename detail::remove_const_helper::value>::type type; +}; +template struct remove_const{ typedef T& type; }; + +// convert a type T to a non-cv-qualified type - remove_cv +template +struct remove_cv +{ + typedef typename detail::cv_traits_imp::unqualified_type type; +}; +template struct remove_cv{ typedef T& type; }; + +//* is a type T declared const - is_const +template +struct is_const +{ + BOOST_DECL_MC(bool, value, detail::cv_traits_imp::is_const); +}; + +//* is a type T declared volatile - is_volatile +template +struct is_volatile +{ + BOOST_DECL_MC(bool, value, detail::cv_traits_imp::is_volatile); +}; + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// The following three don't work: +template struct remove_volatile{ typedef T type; }; +template struct remove_const{ typedef T type; }; +template struct remove_cv{ typedef T type; }; + +namespace detail{ + using ::boost::type_traits::yes_type; + using ::boost::type_traits::no_type; + yes_type is_const_helper(const volatile void*); + no_type is_const_helper(volatile void *); + yes_type is_volatile_helper(const volatile void*); + no_type is_volatile_helper(const void *); +} + +template +struct is_const +{ +private: + static T t; +public: + BOOST_DECL_MC(bool, value, (sizeof(detail::yes_type) == sizeof(detail::is_const_helper(&t)))); +}; + +template <> +struct is_const +{ + BOOST_DECL_MC(bool, value, false); +}; +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS +template <> +struct is_const +{ + BOOST_DECL_MC(bool, value, true); +}; +template <> +struct is_const +{ + BOOST_DECL_MC(bool, value, false); +}; +template <> +struct is_const +{ + BOOST_DECL_MC(bool, value, true); +}; +#endif + +template +struct is_volatile +{ +private: + static T t; +public: + BOOST_DECL_MC(bool, value, (sizeof(detail::yes_type) == sizeof(detail::is_volatile_helper(&t)))); +}; + +template <> +struct is_volatile +{ + BOOST_DECL_MC(bool, value, false); +}; +#ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS +template <> +struct is_volatile +{ + BOOST_DECL_MC(bool, value, false); +}; +template <> +struct is_volatile +{ + BOOST_DECL_MC(bool, value, true); +}; +template <> +struct is_volatile +{ + BOOST_DECL_MC(bool, value, true); +}; +#endif + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +} // namespace boost + + +#endif // CV_TYPE_TRAITS_HPP + + diff --git a/include/boost/type_traits/fwd.hpp b/include/boost/type_traits/fwd.hpp new file mode 100644 index 0000000..2aff24e --- /dev/null +++ b/include/boost/type_traits/fwd.hpp @@ -0,0 +1,140 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// +// forward declarations of type_traits classes +// +#ifndef BOOST_FWD_TYPE_TRAITS_HPP +#define BOOST_FWD_TYPE_TRAITS_HPP + +#include + +#ifndef BOOST_CONFIG_HPP +#include +#endif + +// +// Helper macros for builtin compiler support. +// If your compiler has builtin support for any of the following +// traits concepts, then redefine the appropriate macros to pick +// up on the compiler support: +// +// (these should largely ignore cv-qualifiers) +// BOOST_IS_CLASS(T) should evaluate to true if T is a class or struct type +// BOOST_IS_ENUM(T) should evaluate to true if T is an enumerator type +// BOOST_IS_UNION(T) should evaluate to true if T is a union type +// BOOST_IS_POD(T) should evaluate to true if T is a POD type +// BOOST_IS_EMPTY(T) should evaluate to true if T is an empty struct or union +// BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) should evaluate to true if "T x;" has no effect +// BOOST_HAS_TRIVIAL_COPY(T) should evaluate to true if T(t) <==> memcpy +// BOOST_HAS_TRIVIAL_ASSIGN(T) should evaluate to true if t = u <==> memcpy +// BOOST_HAS_TRIVIAL_DESTRUCTOR(T) should evaluate to true if ~T() has no effect + +#define BOOST_IS_CLASS(T) false +#define BOOST_IS_ENUM(T) false +#define BOOST_IS_UNION(T) false +#define BOOST_IS_POD(T) false +#define BOOST_IS_EMPTY(T) false +#define BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) false +#define BOOST_HAS_TRIVIAL_COPY(T) false +#define BOOST_HAS_TRIVIAL_ASSIGN(T) false +#define BOOST_HAS_TRIVIAL_DESTRUCTOR(T) false + + +namespace boost{ +// +// forward declare all type traits templates here +// +// conversion_traits.hpp: +template +struct is_convertible; +// alignment_traits.hpp: +template +struct alignment_of; +// arithmetic_traits.hpp: +template +struct is_void; +template +struct is_integral; +template +struct is_float; +template +struct is_arithmetic; +template +struct is_fundamental; + +// cv_traits.hpp: +template +struct is_const; +template +struct is_volatile; +template +struct remove_const; +template +struct remove_volatile; +template +struct remove_cv; + +// composite_traits.hpp: +template +struct is_array; +template +struct is_pointer; +template +struct is_reference; +template +struct is_member_pointer; +template +struct is_enum; +template +struct is_union; + +// object_traits.hpp: +template +struct is_object; +template +struct is_scalar; +template +struct is_class; +template +struct is_compound; +template +struct is_POD; +template +struct has_trivial_constructor; +template +struct has_trivial_copy; +template +struct has_trivial_assign; +template +struct has_trivial_destructor; +template +struct is_empty; + +// transform_traits.hpp: +template +struct remove_reference; +template +struct add_reference; +template +struct remove_bounds; +template +struct remove_pointer; +template +struct add_pointer; + +// same_traits.hpp: +template +struct is_same; + +} // namespace boost + +#endif // BOOST_FWD_TYPE_TRAITS_HPP + + + + diff --git a/include/boost/type_traits/ice.hpp b/include/boost/type_traits/ice.hpp new file mode 100644 index 0000000..e2f72d5 --- /dev/null +++ b/include/boost/type_traits/ice.hpp @@ -0,0 +1,76 @@ + +// (C) Copyright John Maddock and Steve Cleary 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// See http://www.boost.org for most recent version including documentation. +// +// macros and helpers for working with integral-constant-expressions. + +#ifndef BOOST_ICE_TYPE_TRAITS_HPP +#define BOOST_ICE_TYPE_TRAITS_HPP + +#ifndef BOOST_CONFIG_HPP +#include +#endif + +#ifdef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +#define BOOST_DECL_MC(type, name, value) enum{name = value } +#define BOOST_DECL_MC2(type, name, v1, v2) enum{name = v1,v2 } +#else +#define BOOST_DECL_MC(type, name, value) static const type name = value +#define BOOST_DECL_MC2(type, name, v1, v2) static const type name = v1,v2 +#endif + + +namespace boost{ +namespace type_traits{ + +typedef char yes_type; +typedef double no_type; + +template +struct ice_not +{ BOOST_DECL_MC(bool, value, true); }; +template <> +struct ice_not +{ BOOST_DECL_MC(bool, value, false); }; + +template +struct ice_or; +template +struct ice_or +{ + BOOST_DECL_MC(bool, value, true); +}; +template <> +struct ice_or +{ + BOOST_DECL_MC(bool, value, false); +}; + +template +struct ice_and; +template +struct ice_and +{ + BOOST_DECL_MC(bool, value, false); +}; +template <> +struct ice_and +{ + BOOST_DECL_MC(bool, value, true); +}; + + +} // namespace type_traits + +} // namespace boost + +#endif // BOOST_ICE_TYPE_TRAITS_HPP + + + + diff --git a/include/boost/type_traits/object_traits.hpp b/include/boost/type_traits/object_traits.hpp new file mode 100644 index 0000000..662dd6f --- /dev/null +++ b/include/boost/type_traits/object_traits.hpp @@ -0,0 +1,318 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// +// defines object traits classes: +// is_object, is_scalar, is_class, is_compound, is_POD, +// has_trivial_constructor, has_trivial_copy, has_trivial_assign, +// has_trivial_destructor, is_empty. +// + +#ifndef OBJECT_TYPE_TRAITS_HPP +#define OBJECT_TYPE_TRAITS_HPP + +#ifndef BOOST_ICE_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_FWD_TYPE_TRAITS_HPP +#include +#endif +#ifndef COMPOSITE_TYPE_TRAITS_HPP +#include +#endif +#ifndef ARITHMETIC_TYPE_TRAITS_HPP +#include +#endif + +namespace boost{ + +/********************************************** + * + * is_object + * + **********************************************/ +template +struct is_object +{ + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_and< + !::boost::is_reference::value, + !::boost::is_void::value + >::value)); +}; + +/********************************************** + * + * is_scalar + * + **********************************************/ +template +struct is_scalar +{ + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_or< + ::boost::is_arithmetic::value, + ::boost::is_enum::value, + ::boost::is_pointer::value, + ::boost::is_member_pointer::value + >::value)); +}; + +/********************************************** + * + * is_class + * + **********************************************/ +template +struct is_class +{ + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_and< + !::boost::is_union::value, + !::boost::is_scalar::value, + !::boost::is_array::value, + !::boost::is_reference::value, + !::boost::is_void::value + >::value)); +}; + +/********************************************** + * + * is_compound + * + **********************************************/ +template struct is_compound +{ + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_or< + ::boost::is_array::value, + ::boost::is_pointer::value, + ::boost::is_reference::value, + ::boost::is_class::value, + ::boost::is_union::value, + ::boost::is_enum::value, + ::boost::is_member_pointer::value + >::value)); +}; + +/********************************************** + * + * is_POD + * + **********************************************/ +template struct is_POD +{ + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_or< + ::boost::is_scalar::value, + ::boost::is_void::value, + BOOST_IS_POD(T) + >::value)); +}; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct is_POD +{ + BOOST_DECL_MC(bool, value, ::boost::is_POD::value); +}; +#endif + +/********************************************** + * + * has_trivial_constructor + * + **********************************************/ +template +struct has_trivial_constructor +{ + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_or< + ::boost::is_POD::value, + BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) + >::value)); +}; + +/********************************************** + * + * has_trivial_copy + * + **********************************************/ +template +struct has_trivial_copy +{ + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_and< + ::boost::type_traits::ice_or< + ::boost::is_POD::value, + BOOST_HAS_TRIVIAL_COPY(T) + >::value, + !::boost::is_volatile::value + >::value)); +}; + +/********************************************** + * + * has_trivial_assign + * + **********************************************/ +template +struct has_trivial_assign +{ + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_and< + ::boost::type_traits::ice_or< + ::boost::is_POD::value, + BOOST_HAS_TRIVIAL_ASSIGN(T) + >::value, + !::boost::is_const::value, + !::boost::is_volatile::value + >::value)); +}; + +/********************************************** + * + * has_trivial_destructor + * + **********************************************/ +template +struct has_trivial_destructor +{ + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_or< + ::boost::is_POD::value, + BOOST_HAS_TRIVIAL_DESTRUCTOR(T) + >::value)); +}; + +/********************************************** + * + * is_empty + * + **********************************************/ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +namespace detail{ + +template +struct empty_helper_t1 : public T +{ +#ifdef __MWERKS__ + empty_helper_t1(); // hh compiler bug workaround +#endif + int i[256]; +}; +struct empty_helper_t2 { int i[256]; }; + +template +struct empty_helper{ BOOST_DECL_MC(bool, value, false); }; + +template +struct empty_helper +{ + BOOST_DECL_MC(bool, value, + (sizeof(empty_helper_t1) == sizeof(empty_helper_t2))); +}; +} + +template +struct is_empty +{ +private: + typedef typename remove_cv::type cvt; +public: + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_or< + ::boost::detail::empty_helper::value , + ::boost::is_convertible::value + >::value, + BOOST_IS_EMPTY(cvt) + >::value)); +}; + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) + +namespace detail{ + +template +struct empty_helper_t1 : public T +{ + int i[256]; +}; +struct empty_helper_t2 { int i[256]; }; + +template +struct empty_helper_base +{ + enum{ value = (sizeof(empty_helper_t1) == sizeof(empty_helper_t2)) }; +}; + +template +struct empty_helper_nonbase +{ + enum{ value = false }; +}; + +template +struct empty_helper_chooser +{ + template + struct rebind + { + typedef empty_helper_nonbase type; + }; +}; + +template <> +struct empty_helper_chooser +{ + template + struct rebind + { + typedef empty_helper_base type; + }; +}; + +} // namespace detail + +template +struct is_empty +{ +private: + typedef ::boost::detail::empty_helper_chooser< + ::boost::type_traits::ice_and< + !::boost::is_convertible::value, + !::boost::is_convertible::value, + !::boost::is_pointer::value, + !::boost::is_member_pointer::value, + !::boost::is_array::value, + !::boost::is_void::value, + !::boost::is_convertible::value + >::value> chooser; + typedef typename chooser::template rebind bound_type; + typedef typename bound_type::type eh_type; +public: + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_or::value)); +}; + +#else +template struct is_empty +{ enum{ value = BOOST_IS_EMPTY(T) }; }; +#endif // defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +} // namespace boost + +#endif // OBJECT_TYPE_TRAITS_HPP + + + + + + diff --git a/include/boost/type_traits/same_traits.hpp b/include/boost/type_traits/same_traits.hpp new file mode 100644 index 0000000..e94f46a --- /dev/null +++ b/include/boost/type_traits/same_traits.hpp @@ -0,0 +1,90 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant & John Maddock 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// +// defines is_same: + +#ifndef SAME_TRAITS_HPP +#define SAME_TRAITS_HPP + +#ifndef BOOST_ICE_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_FWD_TYPE_TRAITS_HPP +#include +#endif +#if !defined(COMPOSITE_TYPE_TRAITS_HPP) && defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC) +#include +#endif + +namespace boost{ + +/********************************************** + * + * is_same + * + **********************************************/ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +template +struct is_same +{ BOOST_DECL_MC(bool, value, false); }; + +template +struct is_same +{ BOOST_DECL_MC(bool, value, true); }; + +#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +#ifdef BOOST_MSVC + +namespace detail{ + +template +struct is_same_part_1 { + template struct part_2 { enum { value = false }; }; + template<> struct part_2 { enum { value = true }; }; +}; + +} // namespace detail + +template +struct is_same : detail::is_same_part_1::template part_2 {}; + +#else // BOOST_MSVC + +namespace detail{ + template + ::boost::type_traits::yes_type is_same_helper(T*, T*); + ::boost::type_traits::no_type is_same_helper(...); +} + +template +struct is_same +{ +private: + static T t; + static U u; +public: + BOOST_DECL_MC(bool, value, + (::boost::type_traits::ice_and< + (sizeof(type_traits::yes_type) == sizeof(detail::is_same_helper(&t,&u))), + (::boost::is_reference::value == ::boost::is_reference::value), + (sizeof(T) == sizeof(U)) + >::value)); +}; + +#endif // BOOST_MSVC + +#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + +} // namespace boost + +#endif // SAME_TRAITS_HPP + + + diff --git a/include/boost/type_traits/transform_traits.hpp b/include/boost/type_traits/transform_traits.hpp new file mode 100644 index 0000000..e82f40f --- /dev/null +++ b/include/boost/type_traits/transform_traits.hpp @@ -0,0 +1,187 @@ +// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. +// Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. +// +// See http://www.boost.org for most recent version including documentation. +// +// defines traits classes for transforming one type to another: +// remove_reference, add_reference, remove_bounds, remove_pointer. +// + +#ifndef TRANSFORM_TRAITS_HPP +#define TRANSFORM_TRAITS_HPP + +#ifndef BOOST_ICE_TYPE_TRAITS_HPP +#include +#endif +#ifndef BOOST_FWD_TYPE_TRAITS_HPP +#include +#endif +#if !defined(COMPOSITE_TYPE_TRAITS_HPP) && defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +#include +#endif + +namespace boost{ + +/********************************************** + * + * remove_reference + * + **********************************************/ +template +struct remove_reference +{ typedef T type; }; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct remove_reference +{ typedef T type; }; +#endif +#if defined(__BORLANDC__) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) +// these are illegal specialisations; cv-qualifies applied to +// references have no effect according to [8.3.2p1], +// C++ Builder requires them though as it treats cv-qualified +// references as distinct types... +template +struct remove_reference +{ typedef T type; }; +template +struct remove_reference +{ typedef T type; }; +template +struct remove_reference +{ typedef T type; }; +#endif + +/********************************************** + * + * add_reference + * + **********************************************/ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct add_reference +{ typedef T& type; }; +template +struct add_reference +{ typedef T& type; }; +#elif defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) +namespace detail{ + +template +struct reference_adder +{ + template + struct rebind + { + typedef T& type; + }; +}; + +template <> +struct reference_adder +{ + template + struct rebind + { + typedef T type; + }; +}; + +} // namespace detail + +template +struct add_reference +{ +private: + typedef typename detail::reference_adder< ::boost::is_reference::value>::template rebind binder; +public: + typedef typename binder::type type; +}; + +#else +template +struct add_reference +{ typedef T& type; }; +#endif + +/********************************************** + * + * remove_bounds + * + **********************************************/ +template +struct remove_bounds +{ typedef T type; }; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct remove_bounds +{ typedef T type; }; +template +struct remove_bounds +{ typedef const T type; }; +template +struct remove_bounds +{ typedef volatile T type; }; +template +struct remove_bounds +{ typedef const volatile T type; }; +#endif + +/********************************************** + * + * remove_pointer + * + **********************************************/ +template +struct remove_pointer +{ typedef T type; }; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct remove_pointer +{ typedef T type; }; +template +struct remove_pointer +{ typedef T type; }; +template +struct remove_pointer +{ typedef T type; }; +template +struct remove_pointer +{ typedef T type; }; +#endif + +/********************************************** + * + * add_pointer + * + **********************************************/ +template +struct add_pointer +{ +private: + typedef typename remove_reference::type no_ref_type; + typedef typename remove_bounds::type no_b_type; +public: + typedef no_b_type* type; +}; + +} // namespace boost + +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +// +// if there is no partial specialisation support +// include a bunch of full specialisations as a workaround: +// +#include +#else +#define BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(x) +#endif + +#endif // TRANSFORM_TRAITS_HPP + + + + + diff --git a/include/boost/type_traits/transform_traits_spec.hpp b/include/boost/type_traits/transform_traits_spec.hpp new file mode 100644 index 0000000..3d05115 --- /dev/null +++ b/include/boost/type_traits/transform_traits_spec.hpp @@ -0,0 +1,74 @@ + +// Copyright (c) 2001 Aleksey Gurtovoy. +// Permission to copy, use, modify, sell and distribute this software is +// granted provided this copyright notice appears in all copies. +// This software is provided "as is" without express or implied warranty, +// and with no claim as to its suitability for any purpose. + +#ifndef BOOST_TT_TRANSFORM_TRAITS_SPEC_HPP +#define BOOST_TT_TRANSFORM_TRAITS_SPEC_HPP + +#ifndef TRANSFORM_TRAITS_HPP +#include +#endif + +#define BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_CONST_VOLATILE_RANK1(T) \ +template<> struct remove_const { typedef T type; }; \ +template<> struct remove_const { typedef T volatile type; }; \ +template<> struct remove_volatile { typedef T type; }; \ +template<> struct remove_volatile { typedef T const type; }; \ +template<> struct remove_cv { typedef T type; }; \ +template<> struct remove_cv { typedef T type; }; \ +template<> struct remove_cv { typedef T type; }; \ +/**/ + +#define BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_1(T) \ +template<> struct remove_pointer { typedef T type; }; \ +template<> struct remove_reference { typedef T type; }; \ +/**/ + +#define BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_2(T) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_1(T) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_1(T const) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_1(T volatile) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_1(T const volatile) \ +/**/ + +#define BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1(T) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_PTR_REF_RANK_2(T) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_CONST_VOLATILE_RANK1(T) \ +/**/ + +#define BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2(T) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1(T*) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1(T const*) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1(T volatile*) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1(T const volatile*) \ +/**/ + +#define BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(T) \ +namespace boost { \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_1(T) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2(T) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2(T*) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2(T const*) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2(T volatile*) \ +BOOST_TYPE_TRAITS_SPECIALIZATION_REMOVE_ALL_RANK_2(T const volatile*) \ +} \ +/**/ + +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(char) +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(signed char) +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(unsigned char) +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(signed short) +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(unsigned short) +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(signed int) +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(unsigned int) +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(signed long) +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(unsigned long) +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(float) +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(double) +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(long double) + +#endif // BOOST_TT_TRANSFORM_TRAITS_SPEC_HPP + diff --git a/include/boost/type_traits/type_traits_test.hpp b/include/boost/type_traits/type_traits_test.hpp new file mode 100644 index 0000000..8981805 --- /dev/null +++ b/include/boost/type_traits/type_traits_test.hpp @@ -0,0 +1,361 @@ +// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +// common test code for type-traits tests +// WARNING: contains code as well as declarations! + + +#ifndef BOOST_TYPE_TRAITS_TEST_HPP +#define BOOST_TYPE_TRAITS_TEST_HPP +#include +#include +// +// define tests here +unsigned failures = 0; +unsigned test_count = 0; +// +// This must get defined within the test file. +// All compilers have bugs, set this to the number of +// regressions *expected* from a given compiler, +// if there are no workarounds for the bugs, *and* +// the regressions have been investigated. +// +extern unsigned int expected_failures; +// +// proc check_result() +// Checks that there were no regressions: +// +int check_result(int argc, char** argv) +{ + std::cout << test_count << " tests completed, " + << failures << " failures found, " + << expected_failures << " failures expected from this compiler." << std::endl; + if((argc == 2) + && (argv[1][0] == '-') + && (argv[1][1] == 'a') + && (argv[1][2] == 0)) + { + std::cout << "Press any key to continue..."; + std::cin.get(); + } + return (failures == expected_failures) ? 0 : failures; +} + + +// +// this one is to verify that a constant is indeed a +// constant-integral-expression: +// +template +struct checker +{ + static void check(bool, bool, const char*, bool){ ++test_count; } +}; + +template <> +struct checker +{ + static void check(bool o, bool n, const char* name, bool soft) + { + ++test_count; + ++failures; + // if this is a soft test, then failure is expected, + // or may depend upon factors outside our control + // (like compiler options)... + if(soft)++expected_failures; + std::cout << "checking value of " << name << "...failed" << std::endl; + std::cout << "\tfound: " << n << " expected " << o << std::endl; + } +}; + +template +struct type_checker +{ + static void check(const char* TT, const char* TU, const char* expression) + { + ++test_count; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + if((typeid(T) != typeid(U)) + || (::boost::is_reference::value != ::boost::is_reference::value) + || (::boost::is_const::value != ::boost::is_const::value) + || (::boost::is_volatile::value != ::boost::is_volatile::value)) + { +#endif + ++failures; + std::cout << "checking type of " << expression << "...failed" << std::endl; + std::cout << " expected type was " << TT << std::endl; + std::cout << " typeid(" << TT << ") was: " << typeid(T).name() << std::endl; + std::cout << " typeid(" << TU << ") was: " << typeid(U).name() << std::endl; + std::cout << " In template class " << typeid(type_checker).name() << std::endl; +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + } +#endif + } +}; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct type_checker +{ + static void check(const char*, const char*, const char*) + { + ++test_count; + } +}; +#endif + + +#define value_test(v, x) checker<(v == x)>::check(v, x, #x, false); +#define soft_value_test(v, x) checker<(v == x)>::check(v, x, #x, true); + +#define value_fail(v, x) \ + ++test_count; \ + ++failures; \ + std::cout << "checking value of " << #x << "...failed" << std::endl; \ + std::cout << " " #x " does not compile on this compiler" << std::endl; + + +#define type_test(v, x) type_checker::check(#v, #x, #x); +#define type_test3(v, x, z) type_checker::check(#v, #x "," #z, #x "," #z); +#ifndef SHORT_TRANSFORM_TEST +#define transform_check(name, from_suffix, to_suffix)\ + type_test(bool to_suffix, name::type);\ + type_test(char to_suffix, name::type);\ + type_test(wchar_t to_suffix, name::type);\ + type_test(signed char to_suffix, name::type);\ + type_test(unsigned char to_suffix, name::type);\ + type_test(short to_suffix, name::type);\ + type_test(unsigned short to_suffix, name::type);\ + type_test(int to_suffix, name::type);\ + type_test(unsigned int to_suffix, name::type);\ + type_test(long to_suffix, name::type);\ + type_test(unsigned long to_suffix, name::type);\ + type_test(float to_suffix, name::type);\ + type_test(long double to_suffix, name::type);\ + type_test(double to_suffix, name::type);\ + type_test(UDT to_suffix, name::type);\ + type_test(enum1 to_suffix, name::type); +#else +#define transform_check(name, from_suffix, to_suffix)\ + type_test(int to_suffix, name::type);\ + type_test(UDT to_suffix, name::type);\ + type_test(enum1 to_suffix, name::type); +#endif + +#define boost_dummy_macro_param + +template +struct test_align +{ + struct padded + { + char c; + T t; + }; + static void do_it() + { + padded p; + unsigned a = reinterpret_cast(&(p.t)) - reinterpret_cast(&p); + ++test_count; + // only fail if we do not have a multiple of the actual value: + if((a > ::boost::alignment_of::value) || (a % ::boost::alignment_of::value)) + { + ++failures; + std::cout << "checking value of " << typeid(boost::alignment_of).name() << "...failed" << std::endl; + std::cout << "\tfound: " << boost::alignment_of::value << " expected " << a << std::endl; + } + // suppress warnings about unused variables: + (void)p; + (void)a; + } +}; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct test_align +{ + static void do_it() + { + // + // we can't do the usual test because we can't take the address + // of a reference, so check that the result is the same as for a + // pointer type instead: + unsigned a = boost::alignment_of::value; + ++test_count; + if(a != boost::alignment_of::value) + { + ++failures; + std::cout << "checking value of " << typeid(boost::alignment_of).name() << "...failed" << std::endl; + std::cout << "\tfound: " << boost::alignment_of::value << " expected " << a << std::endl; + } + } +}; +#endif + +#define align_test(T) test_align::do_it() + +// +// the following code allows us to test that a particular +// template functions correctly when instanciated inside another template +// (some bugs only show up in that situation). For each template +// we declare one NESTED_DECL(classname) that sets up the template class +// and multiple NESTED_TEST(classname, template-arg) declarations, to carry +// the actual tests: +template +struct nested_test +{ + typedef nested_test type; + bool run_time_value; + const char* what; + nested_test(bool b2, const char* w) : run_time_value(b2), what(w) { check(); } + void check() + { + ++test_count; + if(b != run_time_value) + { + ++failures; + std::cerr << "Mismatch between runtime and compile time values in " << what << std::endl; + } + } +}; + +#define NESTED_DECL(what)\ +template \ +struct BOOST_TT_JOIN(nested_tester_,what){\ + nested_test< (0 != ::boost::what::value)> tester;\ + BOOST_TT_JOIN(nested_tester_,what)(const char* s) : tester(::boost::what::value, s){}\ +}; +#define NESTED_TEST(what, with)\ +{BOOST_TT_JOIN(nested_tester_,what) check(#what "<" #with ">"); (void)check;} + +#define BOOST_TT_JOIN( X, Y ) BOOST_DO_TT_JOIN( X, Y ) +#define BOOST_DO_TT_JOIN( X, Y ) X##Y + + + +// +// define some types to test with: +// +enum enum_UDT{ one, two, three }; +struct UDT +{ + UDT(){}; + ~UDT(){}; + UDT(const UDT&); + UDT& operator=(const UDT&); + int i; + + void f1(); + int f2(); + int f3(int); + int f4(int, float); +}; + +typedef void(*f1)(); +typedef int(*f2)(int); +typedef int(*f3)(int, bool); +typedef void (UDT::*mf1)(); +typedef int (UDT::*mf2)(); +typedef int (UDT::*mf3)(int); +typedef int (UDT::*mf4)(int, float); +typedef int (UDT::*mp); + +// cv-qualifiers applied to reference types should have no effect +// declare these here for later use with is_reference and remove_reference: +# ifdef BOOST_MSVC +# pragma warning(push) +# pragma warning(disable: 4181) +# endif // BOOST_MSVC +typedef int& r_type; +typedef const r_type cr_type; +# ifdef BOOST_MSVC +# pragma warning(pop) +# endif // BOOST_MSVC + +struct POD_UDT { int x; }; +struct empty_UDT{ ~empty_UDT(){}; }; +struct empty_POD_UDT{}; +union union_UDT +{ + int x; + double y; + ~union_UDT(); +}; +union POD_union_UDT +{ + int x; + double y; +}; +union empty_union_UDT +{ + ~empty_union_UDT(); +}; +union empty_POD_union_UDT{}; + +class Base { }; + +class Deriverd : public Base { }; + +class NonDerived { }; + +enum enum1 +{ + one_,two_ +}; + +enum enum2 +{ + three_,four_ +}; + +struct VB +{ + virtual ~VB(){}; +}; + +struct VD : VB +{ + ~VD(){}; +}; +// +// struct non_pointer: +// used to verify that is_pointer does not return +// true for class types that implement operator void*() +// +struct non_pointer +{ + operator void*(){return this;} +}; +struct non_int_pointer +{ + int i; + operator int*(){return &i;} +}; +struct int_constructible +{ + int_constructible(int); +}; +struct int_convertible +{ + operator int(); +}; +// +// struct non_empty: +// used to verify that is_empty does not emit +// spurious warnings or errors. +// +struct non_empty : boost::noncopyable +{ + int i; +}; + + + +#endif // BOOST_TYPE_TRAITS_TEST_HPP + + + + + + diff --git a/index.htm b/index.htm new file mode 100644 index 0000000..54b5b0e --- /dev/null +++ b/index.htm @@ -0,0 +1,1202 @@ + + + + + + +Type Traits + + + + +

Header +<boost/type_traits.hpp>

+ +

The contents of <boost/type_traits.hpp> are declared in +namespace boost.

+ +

The file <boost/type_traits.hpp> +contains various template classes that describe the fundamental +properties of a type; each class represents a single type +property or a single type transformation. If you are new to this +library then read the accompanying article +first.

+ +

This documentation is divided up into the following sections:

+ +
Primary Type Categorisation
+Secondary Type Categorisation
+Type Properties
+Relationships Between Types
+Transformations Between Types
+Compiler Support Information
+Type traits headers
+Example Code
+ +

 

+ +

Primary Type Categorisation

+ +

The following type traits templates identify which type +category the type belongs to. For any given type, exactly one of +the following expressions will evaluate to true. Note that this +means that is_integral<T>::value and is_float<T>::value +will only every be true for built-in types; if you want to check +for a user-defined type that may behave "as if" it is +an integral or floating point type, then use the std::numeric_limits +template instead.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 

Expression

+

Description

+

Reference

+

Compiler requirements

+
 
 ::boost::is_void<T>::valueEvaluates + to true only if T is a cv-qualified void type.

3.9.1p9

+
  
 ::boost::is_integral<T>::valueEvaluates + to true only if T is an cv-qualified integral type.

3.9.1p7

+
  
 ::boost::is_float<T>::valueEvaluates + to true only if T is a cv-qualified floating point type.

3.9.1p8

+
  
 ::boost::is_pointer<T>::valueEvaluates + to true only if T is cv-qualified pointer type (includes + function pointers, but excludes pointers to members).

3.9.2p2

+

8.3.1

+
  
 ::boost::is_reference<T>::valueEvaluates + to true only if T is a reference type.

3.9.2

+

8.3.2

+
If the + compiler does not support partial-specialisation of class + templates, then references to types that are both const + and volatile qualified will not be correctly identified. 
 ::boost::is_member_pointer<T>::valueEvaluates + to true only if T is a cv-qualified pointer to a data-member + or member-function.

3.9.2

+

8.3.3

+
On some + compilers, member function pointers may be incorrectly + identified as regular pointers. 
 ::boost::is_array<T>::valueEvaluates + to true only if T is an array type.

3.9.2

+

8.3.4

+
If the + compiler does not support partial-specialisation of class + templates, then some types may be incorrectly identified + as arrays (mainly function types). 
 ::boost::is_union<T>::valueEvaluates + to true only if T is of union type. Currently requires + some kind of compiler support, otherwise unions are + identified as classes.

3.9.2

+

9.5

+
C 
 ::boost::is_class<T>::valueEvaluates + to true only if T is of class/struct type.

3.9.2

+

9.2

+
C 
 ::boost::is_enum<T>::valueEvaluates + to true only if T is of enum type.

3.9.2

+

7.2

+
Requires a + correctly functioning is_convertible template (this means + that is_enum is currently broken under Borland C++). 
+ +

 

+ +

Secondary Type Categorisation

+ +

The following type categories are made up of the union of one +or more primary type categorisations. A type may belong to more +than one of these categories, in addition to one of the primary +categories.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 

Expression

+

Description

+

Reference

+

Compiler requirements

+
 
 ::boost::is_arithmetic<T>::valueEvaluates + to true only if T is a cv-qualified arithmetic type. That + is either an integral or floating point type.

3.9.1p8

+
  
 ::boost::is_fundamental<T>::valueEvaluates + to true only if T is an cv-qualified fundamental type. + That is either an integral, a floating point, or a void + type.

3.9.1

+
  
 ::boost::is_object<T>::valueEvaluates + to true only if T is a cv-qualified object type. That is + not a function, reference, or void type.

3.9p9

+
  
 ::boost::is_scalar<T>::valueEvaluates + to true only if T is cv-qualified scalar type. That is an + arithmetic, a pointer or a pointer to member type.

3.9p10

+
  
 ::boost::is_compound<T>::valueEvaluates + to true only if T is a compound type. That is an array, + function, pointer, reference, enumerator, union, class or + member function type.

3.9.2

+
  
+ +

 

+ +

Type Properties

+ +

The following templates identify the properties that a type +has.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 

Expression

+

Description

+

Reference

+

Compiler requirements

+
 
 ::boost::alignment_of<T>::valueIdentifies + the alignment requirements of T. Actually returns a value + that is only guaranteed to be a multiple of the actual + alignment requirements of T   
 ::boost::is_empty<T>::valueTrue if T + is an empty struct or class. If the compiler implements + the "zero sized empty base classes" + optimisation, then is_empty will correctly guess whether + T is empty. Relies upon is_class to determine whether T + is a class type.

10p5

+

PCD

+
 
 ::boost::is_const<T>::valueEvaluates + to true only if T is top-level const-qualified.

3.9.3

+
  
 ::boost::is_volatile<T>::valueEvaluates + to true only if T is volatile-qualified.

3.9.3

+
  
 ::boost::is_POD<T>::valueEvaluates + to true only if T is a cv-qualified POD type.

3.9p10

+

9p4

+
  
 ::boost::has_trivial_constructor<T>::valueTrue if T + has a trivial default constructor - that is T() is + equivalent to memset. 

PC

+
 
 ::boost::has_trivial_copy<T>::valueTrue if T + has a trivial copy constructor - that is T(const T&) + is equivalent to memcpy. 

PC

+
 
 ::boost::has_trivial_assign<T>::valueTrue if T + has a trivial assignment operator - that is if T::operator=(const + T&) is equivalent to memcpy. 

PC

+
 
 ::boost::has_trivial_destructor<T>::valueTrue if T + has a trivial destructor - that is if T::~T() has no + effect. 

PC

+
 
+ +

 

+ +

Relationships Between Types

+ +

The following templates determine the whether there is a +relationship between two types:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
 

Expression

+

Description

+

Reference

+

Compiler requirements

+
 
 
::boost::is_same<T,U>::value
+

Evaluates to true if T and U are the same + type.

+
   
 ::boost::is_convertible<T,U>::valueEvaluates + to true if type T is convertible to type U.

4

+

8.5

+
Note that + this template is currently broken with Borland's + compiler, for constructor-based conversions. 
+ +

 

+ +

Transformations Between Types

+ +

The following templates transform one type to another, based +upon some well-defined rule. Each template has a single member +called type that is the result of applying the +transformation to the template argument T:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 

Expression

+

Description

+

Reference

+

Compiler requirements

+
 
 ::boost::remove_const<T>::typeCreates a + type the same as T but with any top level const qualifier + removed. For example "const int" would become + "int", but "const int*" would remain + unchanged.3.9.3

P

+
 
 ::boost::remove_volatile<T>::typeCreates a + type the same as T but with any top level volatile + qualifier removed. For example "volatile int" + would become "int".

3.9.3

+

P

+
 
 ::boost::remove_reference<T>::typeIf T is a + reference type then removes the reference, otherwise + leaves T unchanged. For example "int&" + becomes "int" but "int*" remains + unchanged.8.3.2

P

+
 
 ::boost::remove_bounds<T>::typeIf T is an + array type then removes the top level array qualifier + from T, otherwise leaves T unchanged. For example "int[2][3]" + becomes "int[3]".8.3.4

P

+
 
 ::boost::remove_pointer<T>::typeIf T is a + pointer type, then removes the top-level indirection from + T, otherwise leaves T unchanged. For example "int*" + becomes "int", but "int&" remains + unchanged.8.3.1

P

+
 
 ::boost::add_reference<T>::typeIf T is a + reference type then leaves T unchanged, otherwise + converts T to a reference type. For example "int&" + remains unchanged, but "double" becomes "double&".8.3.2

P

+
 
 ::boost::add_pointer<T>::typeIf "t" + is an instance of T, then add_pointer<T>::type is + the type returned by "&t". For example + "int", "int&", "int[2]" + and "int (&)[2]" all become "int*".8.3.1

P

+
 
+ +

As the table above indicates, support for partial +specialization of class templates is required to correctly +implement the type transformation templates. On the other hand, +practice shows that many of the templates from this category are +very useful, and often essential for implementing some generic +libraries. Lack of these templates is often one of the major +limiting factors in porting those libraries to compilers that do +not yet support this language feature. As some of these compilers +are going to be around for a while, and at least one of them is +very wide-spread, it was decided that the library should provide +workarounds where possible. The basic idea behind the workaround +is

+ +
    +
  1. To manually define full specializations of all type + transformation templates for all fundamental types, and + all their 1st and 2nd rank cv-[un]qualified derivative + pointer types, and to
  2. +
  3. Provide a user-level macro that will define such explicit + specializations for any user-defined type T.
  4. +
+ +

The first part guarantees the successful compilation of +something like this:

+ +
BOOST_STATIC_ASSERT((is_same<char, remove_reference<char&>::type>::value));
+ +
BOOST_STATIC_ASSERT((is_same<char const, remove_reference<char const&>::type>::value));
+ +
BOOST_STATIC_ASSERT((is_same<char volatile, remove_reference<char volatile&>::type>::value));
+ +
BOOST_STATIC_ASSERT((is_same<char const volatile, remove_reference<char const volatile&>::type>::value));
+ +
BOOST_STATIC_ASSERT((is_same<char*, remove_reference<char*&>::type>::value));
+ +
BOOST_STATIC_ASSERT((is_same<char const*, remove_reference<char const*&>::type>::value));
+ +
...
+ +
BOOST_STATIC_ASSERT((is_same<char const volatile* const volatile* const volatile, remove_reference<char const volatile* const volatile* const volatile&>::type>::value));
+ +

and the second part provides library's users with a mechanism +to make the above code work not only for 'char', 'int' or other +built-in type, but for they own types too:

+ +
struct my {};
+ +
BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(my)
+ +
BOOST_STATIC_ASSERT((is_same<my, remove_reference<my&>::type>::value));
+ +
BOOST_STATIC_ASSERT((is_same<my, remove_const<my const>::type>::value));
+ +
// etc.
+ +

Note that the maco +BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION evaluates to +nothing on those compilers that do support partial specialisation.

+ +

Compiler Support Information

+ +

The legends used in the tables above have the following +meanings:

+ + + + + + + + + + + + + + +

P

+
Denotes that the class + requires support for partial specialisation of class + templates to work correctly.

C

+
Denotes that direct compiler + support for that traits class is required.

D

+
Denotes that the traits + class is dependent upon a class that requires direct + compiler support.
+ +

 

+ +

For those classes that are marked with a D or C, if compiler +support is not provided, this type trait may return "false" +when the correct value is actually "true". The single +exception to this rule is "is_class", which attempts to +guess whether or not T is really a class, and may return "true" +when the correct value is actually "false". This can +happen if: T is a union or T is a compiler-supplied scalar type +that is not specialised for in these type traits.

+ +

If there is no compiler support, to ensure that these +traits always return the correct values, specialise +'is_union' for each user-defined union type, 'is_empty' for each +user-defined empty composite type, and 'is_POD' for each user-defined +POD type. The 'has_*' traits should also be specialized if the +user-defined type has those traits and is not a POD.

+ +

The following rules are automatically enforced:

+ +

is_enum implies is_POD

+ +

is_POD implies has_*

+ +

This means, for example, if you have an empty POD-struct, just +specialize is_empty and is_POD, which will cause all the has_* to +also return true.

+ +

Type Traits Headers

+ +

The type traits library is normally included with:

+ +

#include <boost/type_traits.hpp>

+ +

However the library is actually split up into a number of +smaller headers, sometimes it can be convenient to include one of +these directly in order to get just those type traits classes you +actually need. Note however that the type traits classes are +highly interdependent - so you may not save as much as you think +this way. The following table lists the type traits classes in +alphabetical order, along with the header that contains each +template.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Template + classHeader 
 add_pointer<boost/type_traits/transform_traits.hpp> 
 add_reference<boost/type_traits/transform_traits.hpp> 
 alignment_of<boost.type_traits/alignment_traits.hpp> 
 has_trivial_assign<boost/type_traits/object_traits.hpp> 
 has_trivial_constructor<boost/type_traits/object_traits.hpp> 
 has_trivial_copy<boost/type_traits/object_traits.hpp> 
 has_trivial_destructor<boost/type_traits/object_traits.hpp> 
 is_arithmetic<boost/type_traits/arithmetic_traits.hpp> 
 is_array + <boost/type_traits/composite_traits.hpp> 
 is_class<boost/type_traits/object_traits.hpp> 
 is_compound<boost/type_traits/object_traits.hpp> 
 is_const<boost/type_traits/cv_traits.hpp> 
 is_convertible<boost/type_traits/conversion_traits.hpp> 
 is_empty<boost/type_traits/object_traits.hpp> 
 is_enum<boost/type_traits/composite_traits.hpp> 
 is_float<boost/type_traits/arithmetic_traits.hpp> 
 is_fundamental<boost/type_traits/arithmetic_traits.hpp> 
 is_integral<boost/type_traits/arithmetic_traits.hpp> 
 is_member_pointer<boost/type_traits/composite_traits.hpp> 
 is_object + <boost/type_traits/object_traits.hpp> 
 is_POD<boost/type_traits/object_traits.hpp> 
 is_pointer<boost/type_traits/composite_traits.hpp> 
 is_reference<boost/type_traits/composite_traits.hpp> 
 is_same<boost/type_traits/same_traits.hpp> 
 is_scalar<boost/type_traits/object_traits.hpp> 
 is_union<boost/type_traits/composite_traits.hpp> 
 is_void<boost/type_traits/arithmetic_traits.hpp> 
 is_volatile<boost/type_traits/cv_traits.hpp> 
 remove_bounds<boost/type_traits/transform_traits.hpp> 
 remove_const<boost/type_traits/cv_traits.hpp> 
 remove_cv<boost/type_traits/cv_traits.hpp> 
 remove_pointer<boost/type_traits/transform_traits.hpp> 
 remove_reference + <boost/type_traits/transform_traits.hpp> 
 remove_volatile<boost/type_traits/cv_traits.hpp> 
+ +

 

+ +

Example code

+ +

Type-traits comes with four example programs that illustrate +some of the ways in which the type traits templates may be used:

+ +

Copy_example.cpp

+ +

Demonstrates a version of std::copy that uses memcpy where +appropriate to optimise the copy operation;

+ +
//
+// opt::copy
+// same semantics as std::copy
+// calls memcpy where appropiate.
+//
+
+namespace detail{
+
+template<typename I1, typename I2>
+I2 copy_imp(I1 first, I1 last, I2 out)
+{
+   while(first != last)
+   {
+      *out = *first;
+      ++out;
+      ++first;
+   }
+   return out;
+}
+
+template <bool b>
+struct copier
+{
+   template<typename I1, typename I2>
+   static I2 do_copy(I1 first, I1 last, I2 out)
+   { return copy_imp(first, last, out); }
+};
+
+template <>
+struct copier<true>
+{
+   template<typename I1, typename I2>
+   static I2* do_copy(I1* first, I1* last, I2* out)
+   {
+      memcpy(out, first, (last-first)*sizeof(I2));
+      return out+(last-first);
+   }
+};
+
+
+}
+
+template<typename I1, typename I2>
+inline I2 copy(I1 first, I1 last, I2 out)
+{
+   typedef typename boost::remove_cv<typename std::iterator_traits<I1>::value_type>::type v1_t;
+   typedef typename boost::remove_cv<typename std::iterator_traits<I2>::value_type>::type v2_t;
+   return detail::copier<
+      ::boost::type_traits::ice_and<
+         ::boost::is_same<v1_t, v2_t>::value,
+         ::boost::is_pointer<I1>::value,
+         ::boost::is_pointer<I2>::value,
+         ::boost::has_trivial_assign<v1_t>::value
+      >::value>::do_copy(first, last, out);
+}
+ +

fill_example.cpp

+ +

Demonstrates a version of std::fill that uses memset where +appropriate to optimise fill operations. Also uses call_traits to +optimise parameter passing, to avoid aliasing issues:

+ +
namespace opt{
+//
+// fill
+// same as std::fill, uses memset where appropriate, along with call_traits
+// to "optimise" parameter passing.
+//
+namespace detail{
+
+template <typename I, typename T>
+void do_fill_(I first, I last, typename boost::call_traits<T>::param_type val)
+{
+   while(first != last)
+   {
+      *first = val;
+      ++first;
+   }
+}
+
+template <bool opt>
+struct filler
+{
+   template <typename I, typename T>
+   struct rebind
+   {
+      static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val)
+      { do_fill_<I,T>(first, last, val); }
+   };
+};
+
+template <>
+struct filler<true>
+{
+   template <typename I, typename T>
+   struct rebind
+   {
+      static void do_fill(I first, I last, T val)
+      {
+         std::memset(first, val, last-first);
+      }
+   };
+};
+
+}
+
+template <class I, class T>
+inline void fill(I first, I last, const T& val)
+{
+   typedef detail::filler<
+      ::boost::type_traits::ice_and<
+         ::boost::is_pointer<I>::value,
+         ::boost::is_arithmetic<T>::value,
+         (sizeof(T) == 1)
+      >::value> filler_t;
+   typedef typename filler_t:: template rebind<I,T> binder;
+   binder::do_fill(first, last, val);
+}
+
+};   // namespace opt
+ +

iter_swap_example.cpp

+ +

Demonstrates a version of std::iter_swap that works with +proxying iterators, as well as regular ones; calls std::swap for +regular iterators, otherwise does a "slow but safe" +swap:

+ +
namespace opt{
+//
+// iter_swap:
+// tests whether iterator is a proxying iterator or not, and
+// uses optimal form accordingly:
+//
+namespace detail{
+
+template <bool b>
+struct swapper
+{
+   template <typename I>
+   static void do_swap(I one, I two)
+   {
+      typedef typename std::iterator_traits<I>::value_type v_t;
+      v_t v = *one;
+      *one = *two;
+      *two = v;
+   }
+};
+
+template <>
+struct swapper<true>
+{
+   template <typename I>
+   static void do_swap(I one, I two)
+   {
+      using std::swap;
+      swap(*one, *two);
+   }
+};
+
+}
+
+template <typename I1, typename I2>
+inline void iter_swap(I1 one, I2 two)
+{
+   typedef typename std::iterator_traits<I1>::reference r1_t;
+   typedef typename std::iterator_traits<I2>::reference r2_t;
+   detail::swapper<
+      ::boost::type_traits::ice_and<
+         ::boost::is_reference<r1_t>::value, 
+         ::boost::is_reference<r2_t>::value,
+         ::boost::is_same<r1_t, r2_t>::value
+      >::value>::do_swap(one, two);
+}
+
+};   // namespace opt
+ +

Trivial_destructor_example.cpp

+ +

This algorithm is the reverse of std::unitialized_copy; it +takes a block of initialized memory and calls destructors on all +objects therein. This would typically be used inside container +classes that manage their own memory:

+ +
namespace opt{
+//
+// algorithm destroy_array:
+// The reverse of std::unitialized_copy, takes a block of
+// initialized memory and calls destructors on all objects therein.
+//
+
+namespace detail{
+
+template <bool>
+struct array_destroyer
+{
+   template <class T>
+   static void destroy_array(T* i, T* j){ do_destroy_array(i, j); }
+};
+
+template <>
+struct array_destroyer<true>
+{
+   template <class T>
+   static void destroy_array(T*, T*){}
+};
+
+template <class T>
+void do_destroy_array(T* first, T* last)
+{
+   while(first != last)
+   {
+      first->~T();
+      ++first;
+   }
+}
+
+}; // namespace detail
+
+template <class T>
+inline void destroy_array(T* p1, T* p2)
+{
+   detail::array_destroyer<boost::has_trivial_destructor<T>::value>::destroy_array(p1, p2);
+}
+} // namespace opt
+ +
+ +

Revised 01 Feb 2001

+ +

© Copyright John Maddock 2001. Permission to copy, use, +modify, sell and distribute this document is granted provided +this copyright notice appears in all copies. This document is +provided "as is" without express or implied warranty, +and with no claim as to its suitability for any purpose.

+ +

The type traits library is based on contributions by Steve +Cleary, Beman Dawes, Aleksey Gurtovoy, Howard Hinnant, John +Maddock and Jeremy Siek.

+ +

Maintained by John +Maddock, the latest version of this file can be found at www.boost.org, and the boost +discussion list at www.egroups.com/list/boost.

+ + diff --git a/tests/alignment_test.cpp b/tests/alignment_test.cpp new file mode 100644 index 0000000..b7c2a6f --- /dev/null +++ b/tests/alignment_test.cpp @@ -0,0 +1,44 @@ + +// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#include +#include + +#ifdef __BORLANDC__ +#pragma hrdstop +#endif +#include "boost/type_traits/type_traits_test.hpp" + +NESTED_DECL(alignment_of) + +int main(int argc, char* argv[]) +{ + NESTED_TEST(alignment_of, int) + NESTED_TEST(alignment_of, int_constructible) + + align_test(int); + align_test(char); + align_test(double); + align_test(int[4]); + align_test(int(*)(int)); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + align_test(char&); + align_test(char (&)(int)); + align_test(char(&)[4]); +#endif + align_test(int*); + //align_test(const int); + align_test(VB); + align_test(VD); + value_test(0, ::boost::alignment_of::value); + + return check_result(argc, argv); +} + +// +// define the number of failures expected for given compilers: +unsigned int expected_failures = 0; + diff --git a/tests/arithmetic_traits_test.cpp b/tests/arithmetic_traits_test.cpp new file mode 100644 index 0000000..87d2d31 --- /dev/null +++ b/tests/arithmetic_traits_test.cpp @@ -0,0 +1,197 @@ + +// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#include +#include + +#ifdef __BORLANDC__ +#pragma hrdstop +#endif +#include "boost/type_traits/type_traits_test.hpp" + +NESTED_DECL(is_void) +NESTED_DECL(is_integral) +NESTED_DECL(is_float) +NESTED_DECL(is_arithmetic) +NESTED_DECL(is_fundamental) + +int main(int argc, char* argv[]) +{ + NESTED_TEST(is_void, void) + NESTED_TEST(is_void, int) + NESTED_TEST(is_integral, int) + NESTED_TEST(is_integral, float) + NESTED_TEST(is_float, void) + NESTED_TEST(is_float, double) + NESTED_TEST(is_arithmetic, void) + NESTED_TEST(is_arithmetic, int) + NESTED_TEST(is_fundamental, UDT) + NESTED_TEST(is_fundamental, int) + + value_test(true, boost::is_void::value) + value_test(true, boost::is_void::value) + value_test(true, boost::is_void::value) + value_test(true, boost::is_void::value) + value_test(false, boost::is_void::value) + + value_test(false, boost::is_integral::value) + value_test(false, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(false, boost::is_integral::value) + value_test(false, boost::is_integral::value) + value_test(false, boost::is_integral::value) + #ifdef ULLONG_MAX + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + #endif + #if defined(__BORLANDC__) || defined(_MSC_VER) + value_test(true, boost::is_integral<__int64>::value) + value_test(true, boost::is_integral::value) + #endif + //const qualified ints: + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + #ifdef ULLONG_MAX + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + #endif + #if defined(__BORLANDC__) || defined(_MSC_VER) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + #endif + // volatile qualified ints: + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + #ifdef ULLONG_MAX + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + #endif + #if defined(__BORLANDC__) || defined(_MSC_VER) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + #endif + //const qualified ints: + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + #ifdef ULLONG_MAX + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + #endif + #if defined(__BORLANDC__) || defined(_MSC_VER) + value_test(true, boost::is_integral::value) + value_test(true, boost::is_integral::value) + #endif + value_test(true, boost::is_float::value) + value_test(true, boost::is_float::value) + value_test(true, boost::is_float::value) + value_test(true, boost::is_float::value) + value_test(true, boost::is_float::value) + value_test(true, boost::is_float::value) + value_test(true, boost::is_float::value) + value_test(true, boost::is_float::value) + value_test(true, boost::is_float::value) + value_test(true, boost::is_float::value) + value_test(true, boost::is_float::value) + value_test(true, boost::is_float::value) + value_test(false, boost::is_float::value) + value_test(false, boost::is_float::value) + value_test(false, boost::is_float::value) + + + value_test(false, boost::is_arithmetic::value) + value_test(false, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + #ifdef ULLONG_MAX + value_test(true, boost::is_arithmetic::value) + value_test(true, boost::is_arithmetic::value) + #endif + #if defined(__BORLANDC__) || defined(_MSC_VER) + value_test(true, boost::is_arithmetic<__int64>::value) + value_test(true, boost::is_arithmetic::value) + #endif + + value_test(false, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + #ifdef ULLONG_MAX + value_test(true, boost::is_fundamental::value) + value_test(true, boost::is_fundamental::value) + #endif + #if defined(__BORLANDC__) || defined(_MSC_VER) + value_test(true, boost::is_fundamental<__int64>::value) + value_test(true, boost::is_fundamental::value) + #endif + + return check_result(argc, argv); +} + +// +// define the number of failures expected for given compilers: +unsigned int expected_failures = 0; + diff --git a/tests/composite_traits_test.cpp b/tests/composite_traits_test.cpp new file mode 100644 index 0000000..e6e564a --- /dev/null +++ b/tests/composite_traits_test.cpp @@ -0,0 +1,116 @@ + +// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#include +#include + +#ifdef __BORLANDC__ +#pragma hrdstop +#endif +#include "boost/type_traits/type_traits_test.hpp" + +NESTED_DECL(is_array) +NESTED_DECL(is_pointer) +NESTED_DECL(is_reference) + +int main(int argc, char* argv[]) +{ + NESTED_TEST(is_array, int) + NESTED_TEST(is_array, int[2]) + NESTED_TEST(is_array, int[3][4]) + NESTED_TEST(is_array, int const [5]) + NESTED_TEST(is_array, int(&)[2]) + NESTED_TEST(is_array, int (*)(double)) + NESTED_TEST(is_pointer, int) + NESTED_TEST(is_pointer, int*) + NESTED_TEST(is_reference, int) + NESTED_TEST(is_reference, int&) + + value_test(false, boost::is_array::value) + value_test(false, boost::is_array::value) + value_test(false, boost::is_array::value) + value_test(false, boost::is_array::value) + value_test(false, boost::is_array::value) + value_test(false, boost::is_array::value) + value_test(false, boost::is_array::value) + value_test(true, boost::is_array::value) + value_test(true, boost::is_array::value) + value_test(true, boost::is_array::value) + value_test(true, boost::is_array::value) + value_test(true, boost::is_array::value) + value_test(false, boost::is_array::value) + value_test(false, boost::is_array::value) + value_test(false, boost::is_array::value) + + value_test(false, boost::is_pointer::value) + value_test(false, boost::is_pointer::value) + value_test(true, boost::is_pointer::value) + value_test(true, boost::is_pointer::value) + value_test(true, boost::is_pointer::value) + value_test(true, boost::is_pointer::value) + // these were false in previous versions (JM 20 Dec 2000): + value_test(true, boost::is_pointer::value) + value_test(true, boost::is_pointer::value) + value_test(true, boost::is_pointer::value) + // JM 02 Oct 2000: + value_test(false, boost::is_pointer::value) + value_test(false, boost::is_pointer::value) + value_test(false, boost::is_pointer::value) + value_test(false, boost::is_pointer::value) + value_test(false, boost::is_pointer::value) + value_test(false, boost::is_pointer::value) + + value_test(true, boost::is_pointer::value) + value_test(true, boost::is_pointer::value) + value_test(true, boost::is_pointer::value) + // Steve: was 'true', should be 'false', via 3.9.2p3 + value_test(false, boost::is_pointer::value) + value_test(false, boost::is_pointer::value) + value_test(false, boost::is_pointer::value) + value_test(false, boost::is_pointer::value) + + value_test(false, boost::is_reference::value) + value_test(true, boost::is_reference::value) + value_test(true, boost::is_reference::value) + value_test(true, boost::is_reference::value) + value_test(true, boost::is_reference::value) + value_test(true, boost::is_reference::value) + value_test(true, boost::is_reference::value) + value_test(true, boost::is_reference::value) + value_test(false, boost::is_reference::value) + + value_test(false, boost::is_member_pointer::value) + value_test(false, boost::is_member_pointer::value) + value_test(false, boost::is_member_pointer::value) + value_test(false, boost::is_member_pointer::value) + value_test(true, boost::is_member_pointer::value) + value_test(true, boost::is_member_pointer::value) + value_test(true, boost::is_member_pointer::value) + value_test(true, boost::is_member_pointer::value) + value_test(false, boost::is_member_pointer::value) + + value_test(false, boost::is_enum::value) + value_test(true, boost::is_enum::value) + value_test(false, boost::is_enum::value) + value_test(false, boost::is_enum::value) + value_test(false, boost::is_enum::value) + + return check_result(argc, argv); +} + +// +// define the number of failures expected for given compilers: +#ifdef __BORLANDC__ +unsigned int expected_failures = 2; +#elif defined(__GNUC__) +unsigned int expected_failures = 1; // can't handle cv-qualified references +#elif defined(BOOST_MSVC) +unsigned int expected_failures = 1; +#else +unsigned int expected_failures = 0; +#endif + + diff --git a/tests/cv_traits_test.cpp b/tests/cv_traits_test.cpp new file mode 100644 index 0000000..41d8c6a --- /dev/null +++ b/tests/cv_traits_test.cpp @@ -0,0 +1,50 @@ + +// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#include +#include + +#ifdef __BORLANDC__ +#pragma hrdstop +#endif +#include "boost/type_traits/type_traits_test.hpp" + +NESTED_DECL(is_const) +NESTED_DECL(is_volatile) + +int main(int argc, char* argv[]) +{ + NESTED_TEST(is_const, int) + NESTED_TEST(is_const, const int) + NESTED_TEST(is_const, volatile int) + NESTED_TEST(is_volatile, int) + NESTED_TEST(is_volatile, const int) + NESTED_TEST(is_volatile, volatile int) + + value_test(false, boost::is_const::value) + value_test(true, boost::is_const::value) + value_test(false, boost::is_const::value) + value_test(true, boost::is_const::value) + value_test(true, boost::is_const::value) + value_test(true, boost::is_const::value) + value_test(false, boost::is_volatile::value) + value_test(true, boost::is_volatile::value) + value_test(false, boost::is_volatile::value) + value_test(true, boost::is_volatile::value) + value_test(true, boost::is_volatile::value) + value_test(true, boost::is_volatile::value) + + return check_result(argc, argv); +} + +// +// define the number of failures expected for given compilers: +#ifdef BOOST_MSVC +unsigned int expected_failures = 2; +#else +unsigned int expected_failures = 0; +#endif + diff --git a/tests/is_convertible_test.cpp b/tests/is_convertible_test.cpp new file mode 100644 index 0000000..da375b2 --- /dev/null +++ b/tests/is_convertible_test.cpp @@ -0,0 +1,72 @@ + +// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#include +#include +#include "boost/type_traits/type_traits_test.hpp" + + +int main(int argc, char* argv[]) +{ + value_test(true, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(false, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(false, (boost::is_convertible::value)); + value_test(false, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); +#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) + value_test(false, (boost::is_convertible::value)); + value_test(false, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); +#endif + value_test(true, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(false, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(false, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(false, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(false, (boost::is_convertible::value)); + + value_test(false, (boost::is_convertible::value)); + value_test(false, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(false, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(false, (boost::is_convertible::value)); + + value_test(true, (boost::is_convertible::value)); + value_test(false, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + value_test(true, (boost::is_convertible::value)); + + return check_result(argc, argv); +} + +// +// define the number of failures expected for given compilers: +#ifdef __BORLANDC__ +unsigned int expected_failures = 1; +#else +unsigned int expected_failures = 0; +#endif + + + + + + + diff --git a/tests/is_same_test.cpp b/tests/is_same_test.cpp new file mode 100644 index 0000000..0803d3c --- /dev/null +++ b/tests/is_same_test.cpp @@ -0,0 +1,42 @@ + +// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#include +#include + +#ifdef __BORLANDC__ +#pragma hrdstop +#endif +#include "boost/type_traits/type_traits_test.hpp" + +int main(int argc, char* argv[]) +{ + value_test(true, (::boost::is_same::value)) + value_test(false, (::boost::is_same::value)) + value_test(false, (::boost::is_same::value)) + value_test(false, (::boost::is_same::value)) + value_test(false, (::boost::is_same::value)) + value_test(false, (::boost::is_same::value)) + value_test(false, (::boost::is_same::value)) + value_test(false, (::boost::is_same::value)) + value_test(false, (::boost::is_same::value)) + value_test(false, (::boost::is_same::value)) + value_test(false, (::boost::is_same::value)) + value_test(true, (::boost::is_same::value)) + value_test(false, (::boost::is_same::value)) + + return check_result(argc, argv); +} + +// +// define the number of failures expected for given compilers: +#ifdef BOOST_MSVC +// can't separate void and cv-void: +unsigned int expected_failures = 1; +#else +unsigned int expected_failures = 0; +#endif + diff --git a/tests/object_type_traits_test.cpp b/tests/object_type_traits_test.cpp new file mode 100644 index 0000000..edb9edf --- /dev/null +++ b/tests/object_type_traits_test.cpp @@ -0,0 +1,191 @@ + +// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#include +#include + +#ifdef __BORLANDC__ +#pragma hrdstop +#endif +#include "boost/type_traits/type_traits_test.hpp" + +NESTED_DECL(is_class) +NESTED_DECL(is_object) +NESTED_DECL(is_scalar) +NESTED_DECL(is_compound) +NESTED_DECL(is_POD) + +int main(int argc, char* argv[]) +{ + NESTED_TEST(is_class, int) + NESTED_TEST(is_class, UDT) + NESTED_TEST(is_object, int) + NESTED_TEST(is_object, void) + NESTED_TEST(is_object, UDT) + NESTED_TEST(is_scalar, void) + NESTED_TEST(is_scalar, int) + NESTED_TEST(is_compound, int) + NESTED_TEST(is_compound, UDT) + NESTED_TEST(is_POD, int) + NESTED_TEST(is_POD, UDT) + + value_test(false, boost::is_class::value) + value_test(false, boost::is_class::value) + value_test(false, boost::is_class::value) + value_test(false, boost::is_class::value) + value_test(false, boost::is_class::value) + value_test(false, boost::is_class::value) + value_test(false, boost::is_class::value) + value_test(false, boost::is_class::value) + value_test(false, boost::is_class::value) + value_test(false, boost::is_class::value) + value_test(true, boost::is_class::value) + value_test(true, boost::is_class::value) + value_test(true, boost::is_class::value) + value_test(true, boost::is_class::value) + value_test(true, boost::is_class::value) + value_test(false, boost::is_class::value) + value_test(false, boost::is_class::value) + value_test(false, boost::is_class::value) + value_test(false, boost::is_class::value) + + value_test(true, boost::is_object::value) + value_test(true, boost::is_object::value) + value_test(false, boost::is_object::value) + value_test(false, boost::is_object::value) + + value_test(true, boost::is_scalar::value) + value_test(true, boost::is_scalar::value) + value_test(false, boost::is_scalar::value) + value_test(false, boost::is_scalar::value) + value_test(false, boost::is_scalar::value) + + value_test(true, boost::is_compound::value) + value_test(true, boost::is_compound::value) + value_test(false, boost::is_compound::value) + value_test(false, boost::is_compound::value) + + value_test(true, boost::is_POD::value) + value_test(true, boost::is_POD::value) + value_test(false, boost::is_POD::value) + value_test(true, boost::is_POD::value) + value_test(true, boost::is_POD::value) + value_test(true, boost::is_POD::value) + value_test(false, boost::is_POD::value) + value_test(true, boost::is_POD::value) + value_test(true, boost::is_POD::value) + value_test(true, boost::is_POD::value) + value_test(true, boost::is_POD::value) + value_test(true, boost::is_POD::value) + value_test(false, boost::is_POD::value) + value_test(false, boost::is_POD::value) + value_test(true, boost::is_POD::value) + value_test(true, boost::is_POD::value) + + value_test(true, boost::has_trivial_constructor::value) + value_test(true, boost::has_trivial_constructor::value) + value_test(true, boost::has_trivial_constructor::value) + value_test(true, boost::has_trivial_constructor::value) + value_test(true, boost::has_trivial_constructor::value) + value_test(true, boost::has_trivial_constructor::value) + value_test(true, boost::has_trivial_constructor::value) + value_test(true, boost::has_trivial_constructor::value) + value_test(true, boost::has_trivial_constructor::value) + value_test(true, boost::has_trivial_constructor::value) + value_test(false, boost::has_trivial_constructor::value) + value_test(true, boost::has_trivial_constructor::value) + value_test(true, boost::has_trivial_constructor::value) + value_test(true, boost::has_trivial_constructor::value) + + value_test(true, boost::has_trivial_copy::value) + value_test(true, boost::has_trivial_copy::value) + value_test(true, boost::has_trivial_copy::value) + value_test(true, boost::has_trivial_copy::value) + // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10 + value_test(false, boost::has_trivial_copy::value) + value_test(true, boost::has_trivial_copy::value) + value_test(true, boost::has_trivial_copy::value) + value_test(true, boost::has_trivial_copy::value) + value_test(true, boost::has_trivial_copy::value) + value_test(true, boost::has_trivial_copy::value) + value_test(false, boost::has_trivial_copy::value) + value_test(true, boost::has_trivial_copy::value) + value_test(true, boost::has_trivial_copy::value) + value_test(true, boost::has_trivial_copy::value) + + value_test(true, boost::has_trivial_assign::value) + value_test(true, boost::has_trivial_assign::value) + value_test(false, boost::has_trivial_assign::value) + value_test(false, boost::has_trivial_assign::value) + // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10 + value_test(false, boost::has_trivial_assign::value) + value_test(true, boost::has_trivial_assign::value) + value_test(true, boost::has_trivial_assign::value) + value_test(true, boost::has_trivial_assign::value) + value_test(true, boost::has_trivial_assign::value) + value_test(true, boost::has_trivial_assign::value) + value_test(false, boost::has_trivial_assign::value) + value_test(true, boost::has_trivial_assign::value) + value_test(true, boost::has_trivial_assign::value) + value_test(true, boost::has_trivial_assign::value) + + value_test(true, boost::has_trivial_destructor::value) + value_test(true, boost::has_trivial_destructor::value) + value_test(true, boost::has_trivial_destructor::value) + value_test(true, boost::has_trivial_destructor::value) + value_test(true, boost::has_trivial_destructor::value) + value_test(true, boost::has_trivial_destructor::value) + value_test(true, boost::has_trivial_destructor::value) + value_test(true, boost::has_trivial_destructor::value) + value_test(true, boost::has_trivial_destructor::value) + value_test(true, boost::has_trivial_destructor::value) + value_test(false, boost::has_trivial_destructor::value) + value_test(false, boost::has_trivial_destructor::value) + value_test(true, boost::has_trivial_destructor::value) + value_test(true, boost::has_trivial_destructor::value) + + soft_value_test(false, boost::is_empty::value) + soft_value_test(false, boost::is_empty::value) + soft_value_test(false, boost::is_empty::value) + soft_value_test(false, boost::is_empty::value) +#if defined(__MWERKS__) + // apparent compiler bug causes this to fail to compile: + value_fail(false, boost::is_empty::value) +#else + soft_value_test(false, boost::is_empty::value) +#endif + soft_value_test(false, boost::is_empty::value) + soft_value_test(false, boost::is_empty::value) + soft_value_test(false, boost::is_empty::value) + soft_value_test(true, boost::is_empty::value) + soft_value_test(true, boost::is_empty::value) + // this one will not compile on most compilers, + // because we can't tell the difference between + // unions and classes: + value_fail(true, boost::is_empty::value) + soft_value_test(false, boost::is_empty::value) + soft_value_test(true, boost::is_empty::value) + soft_value_test(false, boost::is_empty::value) + + return check_result(argc, argv); +} + +// +// define the number of failures expected for given compilers: +#ifdef __BORLANDC__ +// can't handle enum's or classes that are POD's +unsigned int expected_failures = 10; +#elif defined(__GNUC__) +// classes that are POD's, or empty: +unsigned int expected_failures = 4; +#elif defined(BOOST_MSVC) +// can't handle classes that are POD's or arrays that are POD's +unsigned int expected_failures = 19; +#else +unsigned int expected_failures = 4; +#endif + + diff --git a/tests/transform_traits_test.cpp b/tests/transform_traits_test.cpp new file mode 100644 index 0000000..75f609c --- /dev/null +++ b/tests/transform_traits_test.cpp @@ -0,0 +1,395 @@ + +// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and +// distribute this software is granted provided this copyright notice appears +// in all copies. This software is provided "as is" without express or implied +// warranty, and with no claim as to its suitability for any purpose. + +#include +#include +#include + +#ifdef __BORLANDC__ +#pragma hrdstop +#endif + +// +// some of these tests, particularly those involving +// the use of the transform_check macro are tantamount +// to "compiler-abuse", and actually hide a *lot* of +// template test code. To prevent "Internal Compiler Error" +// type messages, we have to split these up into lots of +// separate functions: +#if defined(BOOST_MSVC) || (defined(__BORLANDC__) && (__BORLANDC__ < 0x550)) +#define SHORT_TRANSFORM_TEST +#endif +#include "boost/type_traits/type_traits_test.hpp" + +#define BOOST_DECL_TRANSFORM_TEST(name, type, from, to)\ +void name(){ transform_check(type, from, to) } +#define BOOST_DECL_TRANSFORM_TEST3(name, type, from)\ +void name(){ transform_check(type, from, boost_dummy_macro_param) } +#define BOOST_DECL_TRANSFORM_TEST2(name, type)\ +void name(){ transform_check(type, boost_dummy_macro_param, boost_dummy_macro_param) } + +/*********************************************************************** + * + * tests for remove_const: + * + **********************************************************************/ + +BOOST_DECL_TRANSFORM_TEST3(remove_const_test_1, ::boost::remove_const, const) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_2, ::boost::remove_const, volatile, volatile) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_3, ::boost::remove_const, const volatile, volatile) +BOOST_DECL_TRANSFORM_TEST2(remove_const_test_4, ::boost::remove_const) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_6, ::boost::remove_const, *const, *) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_7, ::boost::remove_const, *volatile, *volatile) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_8, ::boost::remove_const, *const volatile, *volatile) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_9, ::boost::remove_const, *, *) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_11, ::boost::remove_const, volatile*, volatile*) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_12, ::boost::remove_const, const[2], [2]) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_13, ::boost::remove_const, volatile[2], volatile[2]) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_14, ::boost::remove_const, const volatile[2], volatile[2]) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_15, ::boost::remove_const, [2], [2]) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_16, ::boost::remove_const, const*, const*) +BOOST_DECL_TRANSFORM_TEST(remove_const_test_17, ::boost::remove_const, const*const, const*) + +void check_remove_const() +{ + remove_const_test_1(); + remove_const_test_2(); + remove_const_test_3(); + remove_const_test_4(); + remove_const_test_6(); + remove_const_test_7(); + remove_const_test_8(); + remove_const_test_9(); + remove_const_test_11(); + remove_const_test_12(); + remove_const_test_13(); + remove_const_test_14(); + remove_const_test_15(); + remove_const_test_16(); + remove_const_test_17(); +} + +/*********************************************************************** + * + * tests for remove_volatile: + * + **********************************************************************/ + +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_1, ::boost::remove_volatile, const, const) +BOOST_DECL_TRANSFORM_TEST3(remove_volatile_test_2, ::boost::remove_volatile, volatile) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_3, ::boost::remove_volatile, const volatile, const) +BOOST_DECL_TRANSFORM_TEST2(remove_volatile_test_4, ::boost::remove_volatile) +BOOST_DECL_TRANSFORM_TEST2(remove_volatile_test_5, ::boost::remove_volatile) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_6, ::boost::remove_volatile, *const, *const) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_7, ::boost::remove_volatile, *volatile, *) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_8, ::boost::remove_volatile, *const volatile, *const) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_9, ::boost::remove_volatile, *, *) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_10, ::boost::remove_volatile, *, *) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_11, ::boost::remove_volatile, volatile*, volatile*) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_12, ::boost::remove_volatile, const[2], const[2]) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_13, ::boost::remove_volatile, volatile[2], [2]) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_14, ::boost::remove_volatile, const volatile[2], const[2]) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_15, ::boost::remove_volatile, [2], [2]) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_16, ::boost::remove_volatile, const*, const*) +BOOST_DECL_TRANSFORM_TEST(remove_volatile_test_17, ::boost::remove_volatile, const*volatile, const*) + +void check_remove_volatile() +{ + remove_volatile_test_1(); + remove_volatile_test_2(); + remove_volatile_test_3(); + remove_volatile_test_4(); + remove_volatile_test_5(); + remove_volatile_test_6(); + remove_volatile_test_7(); + remove_volatile_test_8(); + remove_volatile_test_9(); + remove_volatile_test_10(); + remove_volatile_test_11(); + remove_volatile_test_12(); + remove_volatile_test_13(); + remove_volatile_test_14(); + remove_volatile_test_15(); + remove_volatile_test_16(); + remove_volatile_test_17(); +} + +/*********************************************************************** + * + * tests for remove_cv: + * + **********************************************************************/ + +BOOST_DECL_TRANSFORM_TEST3(remove_cv_test_1, ::boost::remove_cv, const) +BOOST_DECL_TRANSFORM_TEST3(remove_cv_test_2, ::boost::remove_cv, volatile) +BOOST_DECL_TRANSFORM_TEST3(remove_cv_test_3, ::boost::remove_cv, const volatile) +BOOST_DECL_TRANSFORM_TEST2(remove_cv_test_4, ::boost::remove_cv) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_5, ::boost::remove_cv, const &, const&) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_6, ::boost::remove_cv, *const, *) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_7, ::boost::remove_cv, *volatile, *) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_8, ::boost::remove_cv, *const volatile, *) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_9, ::boost::remove_cv, *, *) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_10, ::boost::remove_cv, const*, const*) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_11, ::boost::remove_cv, volatile*, volatile*) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_12, ::boost::remove_cv, const[2], [2]) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_13, ::boost::remove_cv, volatile[2], [2]) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_14, ::boost::remove_cv, const volatile[2], [2]) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_15, ::boost::remove_cv, [2], [2]) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_16, ::boost::remove_cv, const*, const*) +BOOST_DECL_TRANSFORM_TEST(remove_cv_test_17, ::boost::remove_cv, const*volatile, const*) + +void check_remove_cv() +{ + remove_cv_test_1(); + remove_cv_test_2(); + remove_cv_test_3(); + remove_cv_test_4(); + remove_cv_test_5(); + remove_cv_test_6(); + remove_cv_test_7(); + remove_cv_test_8(); + remove_cv_test_9(); + remove_cv_test_10(); + remove_cv_test_11(); + remove_cv_test_12(); + remove_cv_test_13(); + remove_cv_test_14(); + remove_cv_test_15(); + remove_cv_test_16(); + remove_cv_test_17(); +} + +/*********************************************************************** + * + * tests for remove_reference: + * + **********************************************************************/ + +BOOST_DECL_TRANSFORM_TEST(remove_reference_test_1, ::boost::remove_reference, const, const) +BOOST_DECL_TRANSFORM_TEST(remove_reference_test_2, ::boost::remove_reference, volatile, volatile) +BOOST_DECL_TRANSFORM_TEST3(remove_reference_test_3, ::boost::remove_reference, &) +BOOST_DECL_TRANSFORM_TEST2(remove_reference_test_4, ::boost::remove_reference) +BOOST_DECL_TRANSFORM_TEST(remove_reference_test_5, ::boost::remove_reference, const &, const) +BOOST_DECL_TRANSFORM_TEST(remove_reference_test_6, ::boost::remove_reference, *, *) +BOOST_DECL_TRANSFORM_TEST(remove_reference_test_7, ::boost::remove_reference, *volatile, *volatile) +BOOST_DECL_TRANSFORM_TEST3(remove_reference_test_8, ::boost::remove_reference, &) +BOOST_DECL_TRANSFORM_TEST(remove_reference_test_9, ::boost::remove_reference, const &, const) +BOOST_DECL_TRANSFORM_TEST(remove_reference_test_10, ::boost::remove_reference, const*, const*) +BOOST_DECL_TRANSFORM_TEST(remove_reference_test_11, ::boost::remove_reference, volatile*, volatile*) +BOOST_DECL_TRANSFORM_TEST(remove_reference_test_12, ::boost::remove_reference, const[2], const[2]) +BOOST_DECL_TRANSFORM_TEST(remove_reference_test_13, ::boost::remove_reference, (&)[2], [2]) + +void check_remove_reference() +{ + remove_reference_test_1(); + remove_reference_test_2(); + remove_reference_test_3(); + remove_reference_test_4(); + remove_reference_test_5(); + remove_reference_test_6(); + remove_reference_test_7(); + remove_reference_test_8(); + remove_reference_test_9(); + remove_reference_test_10(); + remove_reference_test_11(); + remove_reference_test_12(); + remove_reference_test_13(); +} + +/*********************************************************************** + * + * tests for remove_bounds: + * + **********************************************************************/ + +BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_1, ::boost::remove_bounds, const, const) +BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_2, ::boost::remove_bounds, volatile, volatile) +BOOST_DECL_TRANSFORM_TEST3(remove_bounds_test_3, ::boost::remove_bounds, [2]) +BOOST_DECL_TRANSFORM_TEST2(remove_bounds_test_4, ::boost::remove_bounds) +BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_5, ::boost::remove_bounds, const &, const&) +BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_6, ::boost::remove_bounds, *, *) +BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_7, ::boost::remove_bounds, *volatile, *volatile) +BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_8, ::boost::remove_bounds, const [2], const) +BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_9, ::boost::remove_bounds, const &, const&) +BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_10, ::boost::remove_bounds, const*, const*) +BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_11, ::boost::remove_bounds, volatile*, volatile*) +BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_12, ::boost::remove_bounds, const[2][3], const[3]) +BOOST_DECL_TRANSFORM_TEST(remove_bounds_test_13, ::boost::remove_bounds, (&)[2], (&)[2]) + +void check_remove_bounds() +{ + remove_bounds_test_1(); + remove_bounds_test_2(); + remove_bounds_test_3(); + remove_bounds_test_4(); + remove_bounds_test_5(); + remove_bounds_test_6(); + remove_bounds_test_7(); + remove_bounds_test_8(); + remove_bounds_test_9(); + remove_bounds_test_10(); + remove_bounds_test_11(); + remove_bounds_test_12(); + remove_bounds_test_13(); +} + +/*********************************************************************** + * + * tests for remove_pointer: + * + **********************************************************************/ + +BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_1, ::boost::remove_pointer, const, const) +BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_2, ::boost::remove_pointer, volatile, volatile) +BOOST_DECL_TRANSFORM_TEST3(remove_pointer_test_3, ::boost::remove_pointer, *) +BOOST_DECL_TRANSFORM_TEST2(remove_pointer_test_4, ::boost::remove_pointer) +BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_5, ::boost::remove_pointer, const &, const&) +BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_6, ::boost::remove_pointer, &, &) +BOOST_DECL_TRANSFORM_TEST3(remove_pointer_test_7, ::boost::remove_pointer, *volatile) +BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_8, ::boost::remove_pointer, const [2], const[2]) +BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_9, ::boost::remove_pointer, const &, const&) +BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_10, ::boost::remove_pointer, const*, const) +BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_11, ::boost::remove_pointer, volatile*, volatile) +BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_12, ::boost::remove_pointer, const[2][3], const[2][3]) +BOOST_DECL_TRANSFORM_TEST(remove_pointer_test_13, ::boost::remove_pointer, (&)[2], (&)[2]) + +void check_remove_pointer() +{ + remove_pointer_test_1(); + remove_pointer_test_2(); + remove_pointer_test_3(); + remove_pointer_test_4(); + remove_pointer_test_5(); + remove_pointer_test_6(); + remove_pointer_test_7(); + remove_pointer_test_8(); + remove_pointer_test_9(); + remove_pointer_test_10(); + remove_pointer_test_11(); + remove_pointer_test_12(); + remove_pointer_test_13(); +} + +/*********************************************************************** + * + * tests for add_reference: + * + **********************************************************************/ + +BOOST_DECL_TRANSFORM_TEST(add_reference_test_1, ::boost::add_reference, const, const&) +BOOST_DECL_TRANSFORM_TEST(add_reference_test_2, ::boost::add_reference, volatile, volatile&) +BOOST_DECL_TRANSFORM_TEST(add_reference_test_3, ::boost::add_reference, *, *&) +//BOOST_DECL_TRANSFORM_TEST2(add_reference_test_4, ::boost::add_reference) +BOOST_DECL_TRANSFORM_TEST(add_reference_test_5, ::boost::add_reference, const &, const&) +BOOST_DECL_TRANSFORM_TEST(add_reference_test_6, ::boost::add_reference, &, &) +BOOST_DECL_TRANSFORM_TEST(add_reference_test_7, ::boost::add_reference, *volatile, *volatile&) +BOOST_DECL_TRANSFORM_TEST(add_reference_test_8, ::boost::add_reference, const [2], const (&)[2]) +BOOST_DECL_TRANSFORM_TEST(add_reference_test_9, ::boost::add_reference, const &, const&) +BOOST_DECL_TRANSFORM_TEST(add_reference_test_10, ::boost::add_reference, const*, const*&) +BOOST_DECL_TRANSFORM_TEST(add_reference_test_11, ::boost::add_reference, volatile*, volatile*&) +BOOST_DECL_TRANSFORM_TEST(add_reference_test_12, ::boost::add_reference, const[2][3], const (&)[2][3]) +BOOST_DECL_TRANSFORM_TEST(add_reference_test_13, ::boost::add_reference, (&)[2], (&)[2]) + +void check_add_reference() +{ + add_reference_test_1(); + add_reference_test_2(); + add_reference_test_3(); + //add_reference_test_4(); + add_reference_test_5(); + add_reference_test_6(); + add_reference_test_7(); + add_reference_test_8(); + add_reference_test_9(); + add_reference_test_10(); + add_reference_test_11(); + add_reference_test_12(); + add_reference_test_13(); +} + +/*********************************************************************** + * + * tests for add_pointer: + * + **********************************************************************/ + +BOOST_DECL_TRANSFORM_TEST(add_pointer_test_1, ::boost::add_pointer, const, const*) +BOOST_DECL_TRANSFORM_TEST(add_pointer_test_2, ::boost::add_pointer, volatile, volatile*) +BOOST_DECL_TRANSFORM_TEST(add_pointer_test_3, ::boost::add_pointer, *, **) +//BOOST_DECL_TRANSFORM_TEST2(add_pointer_test_4, ::boost::add_pointer) +BOOST_DECL_TRANSFORM_TEST(add_pointer_test_7, ::boost::add_pointer, *volatile, *volatile*) +BOOST_DECL_TRANSFORM_TEST(add_pointer_test_10, ::boost::add_pointer, const*, const**) +BOOST_DECL_TRANSFORM_TEST(add_pointer_test_11, ::boost::add_pointer, volatile*, volatile**) +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +BOOST_DECL_TRANSFORM_TEST(add_pointer_test_5, ::boost::add_pointer, const &, const*) +BOOST_DECL_TRANSFORM_TEST(add_pointer_test_6, ::boost::add_pointer, &, *) +BOOST_DECL_TRANSFORM_TEST(add_pointer_test_8, ::boost::add_pointer, const [2], const *) +BOOST_DECL_TRANSFORM_TEST(add_pointer_test_9, ::boost::add_pointer, const &, const*) +BOOST_DECL_TRANSFORM_TEST(add_pointer_test_12, ::boost::add_pointer, const[2][3], const (*)[3]) +BOOST_DECL_TRANSFORM_TEST(add_pointer_test_13, ::boost::add_pointer, (&)[2], *) +#endif + +void check_add_pointer() +{ + add_pointer_test_1(); + add_pointer_test_2(); + add_pointer_test_3(); + //add_pointer_test_4(); + add_pointer_test_7(); + add_pointer_test_10(); + add_pointer_test_11(); +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION + add_pointer_test_5(); + add_pointer_test_6(); + add_pointer_test_8(); + add_pointer_test_9(); + add_pointer_test_12(); + add_pointer_test_13(); +#endif +} + + +int main(int argc, char* argv[]) +{ + check_remove_const(); + check_remove_volatile(); + check_remove_cv(); + check_remove_reference(); + check_remove_bounds(); + check_remove_pointer(); + check_add_reference(); + check_add_pointer(); + + type_test(void, boost::remove_const::type) + type_test(void, boost::remove_volatile::type) + type_test(void, boost::remove_cv::type) + + type_test(int, boost::remove_reference::type) + type_test(void, boost::remove_reference::type) + + type_test(void, boost::remove_bounds::type) + type_test(void, boost::remove_pointer::type) + + return check_result(argc, argv); +} + +// +// define the number of failures expected for given compilers: +#ifdef __BORLANDC__ +#ifdef SHORT_TRANSFORM_TEST +unsigned int expected_failures = 97; // cv-qualifiers +#else +unsigned int expected_failures = 422; // cv-qualifiers +#endif +#elif defined(__GNUC__) +unsigned int expected_failures = 1; // cv-qualified references +#else +unsigned int expected_failures = 0; +#endif + + + +