diff --git a/doc/common_type.qbk b/doc/common_type.qbk new file mode 100644 index 0000000..71cfbf6 --- /dev/null +++ b/doc/common_type.qbk @@ -0,0 +1,219 @@ + +[/===================================================================] +[section:common_type common_type] +[/===================================================================] + +[def __declval [@../../../utility/doc/html/declval.html declval]] + + +`#include ` + + namespace boost { + template struct __common_type; + } + + +__common_type is a traits class used to deduce a type common to a several types, useful as the return type of functions +operating on multiple input types such as in mixed-mode arithmetic.. + +The nested typedef `::type` could be defined as follows: + + template + struct common_type; + + template + struct common_type { + typedef typename __common_type::type, V...>::type type; + }; + + template + struct common_type { + typedef T type; + }; + + template + struct common_type { + typedef decltype(__declval() ? __declval() : __declval()) type; + }; + +All parameter types must be complete. This trait is permitted to be specialized by a user if at least one +template parameter is a user-defined type. [*Note:] Such specializations are required when only explicit conversions +are desired among the __common_type arguments. + +Note that when the compiler does not support variadic templates (and the macro BOOST_NO_VARIADIC_TEMPLATES is defined) +then the maximum number of template arguments is 3. + + +[h4 Configuration macros] + +When the compiler does not support static assertions then the user can select the way static assertions are reported. Define + +* BOOST_COMMON_TYPE_USES_STATIC_ASSERT: define it if you want to use Boost.StaticAssert +* BOOST_COMMON_TYPE_USES_MPL_ASSERT: define it if you want to use Boost.MPL static asertions + +The default behavior is to use mpl assertions in this case, but setting BOOST_COMMON_TYPE_USES_STATIC_ASSERT may reduce +compile times and header dependencies somewhat. + +Depending on the static assertion used you will have an hint of the failing assertion either through the symbol or through the text. + +When possible common_type is implemented using `decltype`. Otherwise when BOOST_COMMON_TYPE_DONT_USE_TYPEOF is not defined +it uses Boost.TypeOf. + +[h4 Tutorial] + +In a nutshell, __common_type is a trait that takes 1 or more types, and returns a type which +all of the types will convert to. The default definition demands this conversion be implicit. +However the trait can be specialized for user-defined types which want to limit their inter-type conversions to explicit, +and yet still want to interoperate with the __common_type facility. + +[*Example:] + + template + complex::type> + operator+(complex, complex); + + +In the above example, "mixed-mode" complex arithmetic is allowed. The return type is described by __common_type. +For example the resulting type of adding a `complex` and `complex` might be a `complex`. + +Here is how someone might produce a variadic comparison function: + + template + typename __common_type::type + min(T... t); + +This is a very useful and broadly applicable utility. + +[h4 How to get the common type of types with explicit conversions?] + +Another choice for the author of the preceding operator could be + + template + typename __common_type, complex >::type + operator+(complex, complex); + +As the default definition of __common_type demands the conversion be implicit, we need to specialize the trait for complex types as follows. + + template + struct __common_type, complex > { + typedef complex< __common_type > type; + }; + +[h4 How important is the order of the common_type<> template arguments?] + +The order of the template parameters is important. + +`common_type::type` is not equivalent to `common_type::type`, but to `common_type::type, C>::type`. + +Consider + + struct A {}; + struct B {}; + struct C { + C() {} + C(A const&) {} + C(B const&) {} + C& operator=(C const&) { + return *this; + } + }; + +The following doesn't compile + + typedef boost::common_type::type ABC; // Does not compile + +while + + typedef boost::common_type::type ABC; + +compiles. + +Thus, as `common_type::type` is undefined, `common_type::type` is also undefined. + +It is intended that clients who wish for `common_type` to be well +defined to define it themselves: + + namespace boost + { + + template <> + struct common_type {typedef C type;}; + + } + +Now this client can ask for `common_type` (and get +the same answer). + +Clients wanting to ask `common_type` in any order and get the same result need to add in addition: + + namespace boost + { + + template <> struct common_type + : public common_type {}; + + } + +This is needed as the specialization of `common_type` is not be used implicitly for `common_type`. + +[h4 Can the common_type of two types be a third type?] + +Given the preceding example, one might expect `common_type::type` to be `C` without any intervention from the user. +But the default `common_type<>` implementation doesn't grant that. It is intended that clients who wish for `common_type` +to be well defined to define it themselves: + + namespace boost + { + + template <> + struct common_type {typedef C type;}; + + template <> struct common_type + : public common_type {}; + + } + +Now this client can ask for `common_type`. + +[h4 How common_type behaves with pointers?] + +Consider + + struct C { }: + struct B : C { }; + struct A : C { }; + + +Shouldn't `common_type::type` be `C*`? I would say yes, but the default implementation will make it ill-formed. + +The library could add a specialization for pointers, as + + namespace boost + { + + template + struct common_type { + typedef common_type* type; + }; + } + +But in the absence of a motivating use cases, we prefer not to add more than the standard specifies. + +Of course the user can always make this specialization. + +[h4 Can you explain the pros/cons of common_type against Boost.Typeof?] + +Even if they appear to be close, `__common_type` and `typeof` have +different purposes. You use `typeof` to get the type of an expression, while +you use __common_type to set explicitly the type returned of a template +function. Both are complementary, and indeed __common_type is equivalent to +`decltype(__declval() ? __declval() : __declval())` + +__common_type is also similar to promote_args in boost/math/tools/promotion.hpp, +though it is not exactly the same as promote_args either. __common_type::type simply represents the result of some +operation on T1 and T2, and defaults to the type obtained by putting T1 and T2 into a conditional statement. + +It is meant to be customizable (via specialization) if this default is not appropriate. + +[endsect] + diff --git a/doc/examples.qbk b/doc/examples.qbk index ccab2ae..fdcfb74 100644 --- a/doc/examples.qbk +++ b/doc/examples.qbk @@ -216,5 +216,22 @@ and enum types to double: [endsect] +[section:improved_min Improving std::min with common_type] + +An improved `std::min` function could be written like this: + + template + typename __common_type::type min(T t, T u) + { + return t < u ? t : u; + } + +And now expressions such as: + + min(1, 2.0) + +will actually compile and return the correct type! + +[endsect] [endsect] diff --git a/doc/html/boost_typetraits/background.html b/doc/html/boost_typetraits/background.html index 9c24e88..41c0b33 100644 --- a/doc/html/boost_typetraits/background.html +++ b/doc/html/boost_typetraits/background.html @@ -56,7 +56,7 @@ method available to them.

- + Type Traits

@@ -84,7 +84,7 @@ given.

- + Implementation

@@ -174,7 +174,7 @@ in the default template.

- + Optimized copy

@@ -247,7 +247,7 @@ otherwise it will call the "slow but safe version".

- + Was it worth it?

@@ -280,7 +280,7 @@

-

Table 1.1. Time taken to copy 1000 elements using `copy<const T*, T*>` (times +

Table 1.1. Time taken to copy 1000 elements using `copy<const T*, T*>` (times in micro-seconds)

@@ -379,7 +379,7 @@

- + Pair of References

@@ -416,7 +416,7 @@ to hold non-reference types, references, and constant references:

-

Table 1.2. Required Constructor Argument Types

+

Table 1.2. Required Constructor Argument Types

@@ -481,7 +481,7 @@ adds a reference to its type, unless it is already a reference.

-

Table 1.3. Using add_reference to synthesize the correct constructor type

+

Table 1.3. Using add_reference to synthesize the correct constructor type

@@ -597,7 +597,7 @@ easier to maintain and easier to understand.

- + Conclusion

@@ -610,7 +610,7 @@ can be optimal as well as generic.

- + Acknowledgements

@@ -618,7 +618,7 @@ comments when preparing this article.

- + References
    diff --git a/doc/html/boost_typetraits/category/transform.html b/doc/html/boost_typetraits/category/transform.html index 09fd6bf..ae7900b 100644 --- a/doc/html/boost_typetraits/category/transform.html +++ b/doc/html/boost_typetraits/category/transform.html @@ -57,6 +57,9 @@ template <class T> struct add_volatile; +template <class... T> +struct common_type; + template <class T> struct decay; @@ -97,7 +100,7 @@ struct remove_volatile;
    - + Broken Compiler Workarounds:
    diff --git a/doc/html/boost_typetraits/examples.html b/doc/html/boost_typetraits/examples.html index 71ac2ef..938122c 100644 --- a/doc/html/boost_typetraits/examples.html +++ b/doc/html/boost_typetraits/examples.html @@ -37,6 +37,8 @@ of std::iter_swap
    Convert Numeric Types and Enums to double
    +
    Improving std::min + with common_type
diff --git a/doc/html/boost_typetraits/examples/improved_min.html b/doc/html/boost_typetraits/examples/improved_min.html new file mode 100644 index 0000000..c5451f6 --- /dev/null +++ b/doc/html/boost_typetraits/examples/improved_min.html @@ -0,0 +1,64 @@ + + + +Improving std::min with common_type + + + + + + + + +
+ + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ An improved std::min function could be written like this: +

+
template <class T, class U>
+typename common_type<T, U>::type min(T t, T u)
+{
+   return t < u ? t : u;
+}
+
+

+ And now expressions such as: +

+
min(1, 2.0)
+
+

+ will actually compile and return the correct type! +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/boost_typetraits/examples/to_double.html b/doc/html/boost_typetraits/examples/to_double.html index 9aaa1d1..2365cc2 100644 --- a/doc/html/boost_typetraits/examples/to_double.html +++ b/doc/html/boost_typetraits/examples/to_double.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

-PrevUpHomeNext +PrevUpHomeNext

@@ -52,7 +52,7 @@
-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/boost_typetraits/history.html b/doc/html/boost_typetraits/history.html index 2ba39c1..07985f8 100644 --- a/doc/html/boost_typetraits/history.html +++ b/doc/html/boost_typetraits/history.html @@ -27,7 +27,7 @@ History

- + Boost 1.44.0
    @@ -43,7 +43,7 @@
- + Boost 1.42.0