Boost.Ratio: moved to trunk

[SVN r67575]
This commit is contained in:
Vicente J. Botet Escriba 2011-01-02 16:26:51 +00:00
parent 88da98e37b
commit 3ac9309817
13 changed files with 9883 additions and 0 deletions

73
doc/Jamfile.v2 Normal file
View File

@ -0,0 +1,73 @@
# Boost.Ratio library documentation Jamfile ---------------------------------
#
# Copyright Vicente J. Botet Escriba 2010. Use, modification and
# distribution is subject to the Boost Software License, Version
# 1.0. (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
#
# See http://www.boost.org for updates, documentation, and revision history.
#import doxygen ;
import quickbook ;
#doxygen autodoc
# :
# [ glob ../../../boost/chrono/*.hpp ]
# [ glob ../../../boost/chrono/allocators/*.hpp ]
# :
# <doxygen:param>EXTRACT_ALL=NO
# <doxygen:param>HIDE_UNDOC_MEMBERS=YES
# <doxygen:param>EXTRACT_PRIVATE=NO
# <doxygen:param>EXPAND_ONLY_PREDEF=YES
# <doxygen:param>PREDEFINED=BOOST_INTERPROCESS_DOXYGEN_INVOKED
# <xsl:param>"boost.doxygen.reftitle=Boost.Chrono Reference"
# ;
xml ratio : ratio.qbk ;
boostbook standalone
:
ratio
:
# HTML options first:
# Use graphics not text for navigation:
<xsl:param>navig.graphics=1
# How far down we chunk nested sections, basically all of them:
<xsl:param>chunk.section.depth=0
# Don't put the first section on the same page as the TOC:
<xsl:param>chunk.first.sections=1
# How far down sections get TOC's
<xsl:param>toc.section.depth=4
# Max depth in each TOC:
<xsl:param>toc.max.depth=2
# How far down we go with TOC's
<xsl:param>generate.section.toc.level=10
# Path for links to Boost:
<xsl:param>boost.root=../../../..
# Path for libraries index:
<xsl:param>boost.libraries=../../../../libs/libraries.htm
# Use the main Boost stylesheet:
<xsl:param>html.stylesheet=../../../../doc/src/boostbook.css
# PDF Options:
# TOC Generation: this is needed for FOP-0.9 and later:
<xsl:param>fop1.extensions=0
# Or enable this if you're using XEP:
<xsl:param>xep.extensions=1
# TOC generation: this is needed for FOP 0.2, but must not be set to zero for FOP-0.9!
<xsl:param>fop.extensions=0
# No indent on body text:
<xsl:param>body.start.indent=0pt
# Margin size:
<xsl:param>page.margin.inner=0.5in
# Margin size:
<xsl:param>page.margin.outer=0.5in
# Yes, we want graphics for admonishments:
<xsl:param>admon.graphics=1
# Set this one for PDF generation *only*:
# default pnd graphics are awful in PDF form,
# better use SVG's instead:
<format>pdf:<xsl:param>admon.graphics.extension=".svg"
<format>pdf:<xsl:param>admon.graphics.path=$(boost-images)/
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/libs/regex/doc/html
;

15
doc/index.html Normal file
View File

@ -0,0 +1,15 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=html/index.html">
</head>
<body>
Automatic redirection failed, please go to
<a href="../../doc/html/ratio.html">../../doc/html/ratio.html</a>
<p>&copy; Copyright 2009-2010 Vicente J. Botet Escrib&aacute;.
Distributed under the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</body>
</html>

6740
doc/ratio.pdf Normal file

File diff suppressed because it is too large Load Diff

1256
doc/ratio.qbk Normal file

File diff suppressed because it is too large Load Diff

123
example/config.hpp Normal file
View File

@ -0,0 +1,123 @@
// boost/chrono/config.hpp -------------------------------------------------//
// Copyright Beman Dawes 2003, 2006, 2008
// Copyright 2009 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/chrono for documentation.
#ifndef BOOST_EX_CHRONO_CONFIG_HPP
#define BOOST_EX_CHRONO_CONFIG_HPP
#include <boost/config.hpp>
// BOOST_EX_CHRONO_POSIX_API, BOOST_EX_CHRONO_MAC_API, or BOOST_EX_CHRONO_WINDOWS_API
// can be defined by the user to specify which API should be used
#if defined(BOOST_EX_CHRONO_WINDOWS_API)
# warning Boost.Chrono will use the Windows API
#elif defined(BOOST_EX_CHRONO_MAC_API)
# warning Boost.Chrono will use the Mac API
#elif defined(BOOST_EX_CHRONO_POSIX_API)
# warning Boost.Chrono will use the POSIX API
#endif
# if defined( BOOST_EX_CHRONO_WINDOWS_API ) && defined( BOOST_EX_CHRONO_POSIX_API )
# error both BOOST_EX_CHRONO_WINDOWS_API and BOOST_EX_CHRONO_POSIX_API are defined
# elif defined( BOOST_EX_CHRONO_WINDOWS_API ) && defined( BOOST_EX_CHRONO_MAC_API )
# error both BOOST_EX_CHRONO_WINDOWS_API and BOOST_EX_CHRONO_MAC_API are defined
# elif defined( BOOST_EX_CHRONO_MAC_API ) && defined( BOOST_EX_CHRONO_POSIX_API )
# error both BOOST_EX_CHRONO_MAC_API and BOOST_EX_CHRONO_POSIX_API are defined
# elif !defined( BOOST_EX_CHRONO_WINDOWS_API ) && !defined( BOOST_EX_CHRONO_MAC_API ) && !defined( BOOST_EX_CHRONO_POSIX_API )
# if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32))
# define BOOST_EX_CHRONO_WINDOWS_API
# define BOOST_EX_CHRONO_HAS_CLOCK_MONOTONIC
# define BOOST_EX_CHRONO_HAS_THREAD_CLOCK
# define BOOST_EX_CHRONO_THREAD_CLOCK_IS_MONOTONIC true
# elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
# define BOOST_EX_CHRONO_MAC_API
# define BOOST_EX_CHRONO_HAS_CLOCK_MONOTONIC
# define BOOST_EX_CHRONO_THREAD_CLOCK_IS_MONOTONIC true
# else
# define BOOST_EX_CHRONO_POSIX_API
# endif
# endif
# if defined( BOOST_EX_CHRONO_POSIX_API )
# include <time.h> //to check for CLOCK_REALTIME and CLOCK_MONOTONIC and _POSIX_THREAD_CPUTIME
# if defined(CLOCK_REALTIME)
# if defined(CLOCK_MONOTONIC)
# define BOOST_EX_CHRONO_HAS_CLOCK_MONOTONIC
# endif
# else
# error <time.h> does not supply CLOCK_REALTIME
# endif
# if defined(_POSIX_THREAD_CPUTIME)
# define BOOST_EX_CHRONO_HAS_THREAD_CLOCK
# define BOOST_EX_CHRONO_THREAD_CLOCK_IS_MONOTONIC true
# endif
# endif
// enable dynamic linking on Windows ---------------------------------------//
//# if (defined(BOOST_ALL_DYN_LINK) || defined(BOOST_EX_CHRONO_DYN_LINK)) && defined(__BORLANDC__) && defined(__WIN32__)
//# error Dynamic linking Boost.System does not work for Borland; use static linking instead
//# endif
#ifdef BOOST_HAS_DECLSPEC // defined by boost.config
// we need to import/export our code only if the user has specifically
// asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost
// libraries to be dynamically linked, or BOOST_EX_CHRONO_DYN_LINK
// if they want just this one to be dynamically liked:
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_EX_CHRONO_DYN_LINK)
// export if this is our own source, otherwise import:
#ifdef BOOST_EX_CHRONO_SOURCE
# define BOOST_EX_CHRONO_DECL __declspec(dllexport)
#else
# define BOOST_EX_CHRONO_DECL __declspec(dllimport)
#endif // BOOST_EX_CHRONO_SOURCE
#endif // DYN_LINK
#endif // BOOST_HAS_DECLSPEC
//
// if BOOST_EX_CHRONO_DECL isn't defined yet define it now:
#ifndef BOOST_EX_CHRONO_DECL
#define BOOST_EX_CHRONO_DECL
#endif
// define constexpr related macros ------------------------------//
//~ #include <boost/config.hpp>
#if defined(BOOST_NO_CONSTEXPR)
#define BOOST_EX_CHRONO_CONSTEXPR
#define BOOST_EX_CHRONO_CONST_REF const&
#else
#define BOOST_EX_CHRONO_CONSTEXPR constexpr
#define BOOST_EX_CHRONO_CONST_REF
#endif
// enable automatic library variant selection ------------------------------//
#if !defined(BOOST_EX_CHRONO_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_EX_CHRONO_NO_LIB)
//
// Set the name of our library; this will get undef'ed by auto_link.hpp
// once it's done with it:
//
#define BOOST_LIB_NAME boost_chrono
//
// If we're importing code from a dll, then tell auto_link.hpp about it:
//
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_EX_CHRONO_DYN_LINK)
# define BOOST_DYN_LINK
#endif
//
// And include the header that does the work:
//
#include <boost/config/auto_link.hpp>
#endif // auto-linking disabled
#endif // BOOST_EX_CHRONO_CONFIG_HPP

39
example/display_ex.cpp Normal file
View File

@ -0,0 +1,39 @@
// io_ex2.cpp ----------------------------------------------------------//
// Copyright 2010 Howard Hinnant
// Copyright 2010 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
/*
This code was adapted by Vicente J. Botet Escriba from Hinnant's html documentation.
Many thanks to Howard for making his code available under the Boost license.
*/
#include <iostream>
#include <boost/ratio/ratio_io.hpp>
int main()
{
using namespace std;
using namespace boost;
cout << "ratio_string<deca, char>::long_name() = "
<< ratio_string<deca, char>::long_name() << '\n';
cout << "ratio_string<deca, char>::short_name() = "
<< ratio_string<deca, char>::short_name() << '\n';
cout << "ratio_string<giga, char>::long_name() = "
<< ratio_string<giga, char>::long_name() << '\n';
cout << "ratio_string<giga, char>::short_name() = "
<< ratio_string<giga, char>::short_name() << '\n';
cout << "ratio_string<ratio<4, 6>, char>::long_name() = "
<< ratio_string<ratio<4, 6>, char>::long_name() << '\n';
cout << "ratio_string<ratio<4, 6>, char>::short_name() = "
<< ratio_string<ratio<4, 6>, char>::short_name() << '\n';
return 0;
}

793
example/duration.hpp Normal file
View File

@ -0,0 +1,793 @@
// duration.hpp --------------------------------------------------------------//
// Copyright 2008 Howard Hinnant
// Copyright 2008 Beman Dawes
// Copyright 2009-2010 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
/*
This code was derived by Beman Dawes from Howard Hinnant's time2_demo prototype.
Many thanks to Howard for making his code available under the Boost license.
The original code was modified to conform to Boost conventions and to section
20.9 Time utilities [time] of the C++ committee's working paper N2798.
See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf.
time2_demo contained this comment:
Much thanks to Andrei Alexandrescu,
Walter Brown,
Peter Dimov,
Jeff Garland,
Terry Golubiewski,
Daniel Krugler,
Anthony Williams.
*/
#ifndef BOOST_EX_CHRONO_DURATION_HPP
#define BOOST_EX_CHRONO_DURATION_HPP
#include "config.hpp"
#include "static_assert.hpp"
//~ #include <iostream>
#include <climits>
#include <limits>
#include <boost/mpl/logical.hpp>
#include <boost/ratio.hpp>
#include "type_traits/common_type.hpp"
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_floating_point.hpp>
#include <boost/type_traits/is_unsigned.hpp>
#include <boost/cstdint.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/integer_traits.hpp>
#if !defined(BOOST_NO_STATIC_ASSERT) || !defined(BOOST_EX_CHRONO_USES_MPL_ASSERT)
#define BOOST_EX_CHRONO_A_DURATION_REPRESENTATION_CAN_NOT_BE_A_DURATION "A duration representation can not be a duration"
#define BOOST_EX_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_DURATION_MUST_BE_A_STD_RATIO "Second template parameter of duration must be a boost::ratio"
#define BOOST_EX_CHRONO_DURATION_PERIOD_MUST_BE_POSITIVE "duration period must be positive"
#define BOOST_EX_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_TIME_POINT_MUST_BE_A_BOOST_EX_CHRONO_DURATION "Second template parameter of time_point must be a boost_ex::chrono::duration"
#endif
//----------------------------------------------------------------------------//
// //
// 20.9 Time utilities [time] //
// synopsis //
// //
//----------------------------------------------------------------------------//
namespace boost_ex {
using boost::ratio;
namespace chrono {
template <class Rep, class Period = ratio<1> >
class duration;
namespace detail
{
template <class T>
struct is_duration
: boost::false_type {};
template <class Rep, class Period>
struct is_duration<duration<Rep, Period> >
: boost::true_type {};
//template <class T>
// struct is_duration
// : is_duration<typename boost::remove_cv<T>::type> {};
template <class Duration, class Rep, bool = is_duration<Rep>::value>
struct duration_divide_result
{
};
template <class Duration, class Rep2,
bool = (
(boost::is_convertible<typename Duration::rep,
typename common_type<typename Duration::rep, Rep2>::type>::value)
&& (boost::is_convertible<Rep2,
typename common_type<typename Duration::rep, Rep2>::type>::value)
)
>
struct duration_divide_imp
{
};
template <class Rep1, class Period, class Rep2>
struct duration_divide_imp<duration<Rep1, Period>, Rep2, true>
{
typedef duration<typename common_type<Rep1, Rep2>::type, Period> type;
};
template <class Rep1, class Period, class Rep2>
struct duration_divide_result<duration<Rep1, Period>, Rep2, false>
: duration_divide_imp<duration<Rep1, Period>, Rep2>
{
};
///
template <class Rep, class Duration, bool = is_duration<Rep>::value>
struct duration_divide_result2
{
};
template <class Rep, class Duration,
bool = (
(boost::is_convertible<typename Duration::rep,
typename common_type<typename Duration::rep, Rep>::type>::value)
&& (boost::is_convertible<Rep,
typename common_type<typename Duration::rep, Rep>::type>::value)
)
>
struct duration_divide_imp2
{
};
template <class Rep1, class Rep2, class Period >
struct duration_divide_imp2<Rep1, duration<Rep2, Period>, true>
{
//typedef typename common_type<Rep1, Rep2>::type type;
typedef double type;
};
template <class Rep1, class Rep2, class Period >
struct duration_divide_result2<Rep1, duration<Rep2, Period>, false>
: duration_divide_imp2<Rep1, duration<Rep2, Period> >
{
};
///
template <class Duration, class Rep, bool = is_duration<Rep>::value>
struct duration_modulo_result
{
};
template <class Duration, class Rep2,
bool = (
//boost::is_convertible<typename Duration::rep,
//typename common_type<typename Duration::rep, Rep2>::type>::value
//&&
boost::is_convertible<Rep2,
typename common_type<typename Duration::rep, Rep2>::type>::value
)
>
struct duration_modulo_imp
{
};
template <class Rep1, class Period, class Rep2>
struct duration_modulo_imp<duration<Rep1, Period>, Rep2, true>
{
typedef duration<typename common_type<Rep1, Rep2>::type, Period> type;
};
template <class Rep1, class Period, class Rep2>
struct duration_modulo_result<duration<Rep1, Period>, Rep2, false>
: duration_modulo_imp<duration<Rep1, Period>, Rep2>
{
};
} // namespace detail
} // namespace chrono
// common_type trait specializations
template <class Rep1, class Period1, class Rep2, class Period2>
struct common_type<chrono::duration<Rep1, Period1>,
chrono::duration<Rep2, Period2> >;
namespace chrono {
// customization traits
template <class Rep> struct treat_as_floating_point;
template <class Rep> struct duration_values;
// duration arithmetic
// template <class Rep1, class Period1, class Rep2, class Period2>
// typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
// operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
// template <class Rep1, class Period1, class Rep2, class Period2>
// typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
// operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
// template <class Rep1, class Period, class Rep2>
// typename boost::enable_if_c
// <
// boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>::value
// && boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>::value,
// duration<typename common_type<Rep1, Rep2>::type, Period>
// >::type
// operator*(const duration<Rep1, Period>& d, const Rep2& s);
// template <class Rep1, class Period, class Rep2>
// typename boost::enable_if_c
// <
// boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>::value
// && boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>::value,
// duration<typename common_type<Rep1, Rep2>::type, Period>
// >::type
// operator*(const Rep1& s, const duration<Rep2, Period>& d);
// template <class Rep1, class Period, class Rep2>
// typename boost::disable_if <detail::is_duration<Rep2>,
// typename detail::duration_divide_result<duration<Rep1, Period>, Rep2>::type
// >::type
// operator/(const duration<Rep1, Period>& d, const Rep2& s);
// template <class Rep1, class Period1, class Rep2, class Period2>
// typename common_type<Rep1, Rep2>::type
// operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
// duration comparisons
// template <class Rep1, class Period1, class Rep2, class Period2>
// bool operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
// template <class Rep1, class Period1, class Rep2, class Period2>
// bool operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
// template <class Rep1, class Period1, class Rep2, class Period2>
// bool operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
// template <class Rep1, class Period1, class Rep2, class Period2>
// bool operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
// template <class Rep1, class Period1, class Rep2, class Period2>
// bool operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
// template <class Rep1, class Period1, class Rep2, class Period2>
// bool operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs);
// duration_cast
//template <class ToDuration, class Rep, class Period>
// ToDuration duration_cast(const duration<Rep, Period>& d);
// convenience typedefs
typedef duration<boost::int_least64_t, boost::nano> nanoseconds; // at least 64 bits needed
typedef duration<boost::int_least64_t, boost::micro> microseconds; // at least 55 bits needed
typedef duration<boost::int_least64_t, boost::milli> milliseconds; // at least 45 bits needed
typedef duration<boost::int_least64_t> seconds; // at least 35 bits needed
typedef duration<boost::int_least32_t, ratio< 60> > minutes; // at least 29 bits needed
typedef duration<boost::int_least32_t, ratio<3600> > hours; // at least 23 bits needed
//----------------------------------------------------------------------------//
// duration helpers //
//----------------------------------------------------------------------------//
namespace detail
{
// duration_cast
// duration_cast is the heart of this whole prototype. It can convert any
// duration to any other. It is also (implicitly) used in converting
// time_points. The conversion is always exact if possible. And it is
// always as efficient as hand written code. If different representations
// are involved, care is taken to never require implicit conversions.
// Instead static_cast is used explicitly for every required conversion.
// If there are a mixture of integral and floating point representations,
// the use of common_type ensures that the most logical "intermediate"
// representation is used.
template <class FromDuration, class ToDuration,
class Period = typename boost::ratio_divide<typename FromDuration::period,
typename ToDuration::period>::type,
bool = Period::num == 1,
bool = Period::den == 1>
struct duration_cast;
// When the two periods are the same, all that is left to do is static_cast from
// the source representation to the target representation (which may be a no-op).
// This conversion is always exact as long as the static_cast from the source
// representation to the destination representation is exact.
template <class FromDuration, class ToDuration, class Period>
struct duration_cast<FromDuration, ToDuration, Period, true, true>
{
ToDuration operator()(const FromDuration& fd) const
{
return ToDuration(static_cast<typename ToDuration::rep>(fd.count()));
}
};
// When the numerator of FromPeriod / ToPeriod is 1, then all we need to do is
// divide by the denominator of FromPeriod / ToPeriod. The common_type of
// the two representations is used for the intermediate computation before
// static_cast'ing to the destination.
// This conversion is generally not exact because of the division (but could be
// if you get lucky on the run time value of fd.count()).
template <class FromDuration, class ToDuration, class Period>
struct duration_cast<FromDuration, ToDuration, Period, true, false>
{
ToDuration operator()(const FromDuration& fd) const
{
typedef typename common_type<
typename ToDuration::rep,
typename FromDuration::rep,
intmax_t>::type C;
return ToDuration(static_cast<typename ToDuration::rep>(
static_cast<C>(fd.count()) / static_cast<C>(Period::den)));
}
};
// When the denomenator of FromPeriod / ToPeriod is 1, then all we need to do is
// multiply by the numerator of FromPeriod / ToPeriod. The common_type of
// the two representations is used for the intermediate computation before
// static_cast'ing to the destination.
// This conversion is always exact as long as the static_cast's involved are exact.
template <class FromDuration, class ToDuration, class Period>
struct duration_cast<FromDuration, ToDuration, Period, false, true>
{
ToDuration operator()(const FromDuration& fd) const
{
typedef typename common_type<
typename ToDuration::rep,
typename FromDuration::rep,
intmax_t>::type C;
return ToDuration(static_cast<typename ToDuration::rep>(
static_cast<C>(fd.count()) * static_cast<C>(Period::num)));
}
};
// When neither the numerator or denominator of FromPeriod / ToPeriod is 1, then we need to
// multiply by the numerator and divide by the denominator of FromPeriod / ToPeriod. The
// common_type of the two representations is used for the intermediate computation before
// static_cast'ing to the destination.
// This conversion is generally not exact because of the division (but could be
// if you get lucky on the run time value of fd.count()).
template <class FromDuration, class ToDuration, class Period>
struct duration_cast<FromDuration, ToDuration, Period, false, false>
{
ToDuration operator()(const FromDuration& fd) const
{
typedef typename common_type<
typename ToDuration::rep,
typename FromDuration::rep,
intmax_t>::type C;
return ToDuration(static_cast<typename ToDuration::rep>(
static_cast<C>(fd.count()) * static_cast<C>(Period::num)
/ static_cast<C>(Period::den)));
}
};
} // namespace detail
//----------------------------------------------------------------------------//
// //
// 20.9.2 Time-related traits [time.traits] //
// //
//----------------------------------------------------------------------------//
//----------------------------------------------------------------------------//
// 20.9.2.1 treat_as_floating_point [time.traits.is_fp] //
// Probably should have been treat_as_floating_point. Editor notifed. //
//----------------------------------------------------------------------------//
// Support bidirectional (non-exact) conversions for floating point rep types
// (or user defined rep types which specialize treat_as_floating_point).
template <class Rep>
struct treat_as_floating_point : boost::is_floating_point<Rep> {};
//----------------------------------------------------------------------------//
// 20.9.2.2 duration_values [time.traits.duration_values] //
//----------------------------------------------------------------------------//
namespace detail {
template <class T, bool = boost::is_arithmetic<T>::value>
struct chrono_numeric_limits {
static T lowest() throw() {return (std::numeric_limits<T>::min) ();}
};
template <class T>
struct chrono_numeric_limits<T,true> {
static T lowest() throw() {return (std::numeric_limits<T>::min) ();}
};
template <>
struct chrono_numeric_limits<float,true> {
static float lowest() throw() {return -(std::numeric_limits<float>::max) ();}
};
template <>
struct chrono_numeric_limits<double,true> {
static double lowest() throw() {return -(std::numeric_limits<double>::max) ();}
};
template <>
struct chrono_numeric_limits<long double,true> {
static long double lowest() throw() {return -(std::numeric_limits<long double>::max)();}
};
template <class T>
struct numeric_limits : chrono_numeric_limits<typename boost::remove_cv<T>::type> {};
}
template <class Rep>
struct duration_values
{
static Rep zero() {return Rep(0);}
static Rep max BOOST_PREVENT_MACRO_SUBSTITUTION () {return (std::numeric_limits<Rep>::max)();}
static Rep min BOOST_PREVENT_MACRO_SUBSTITUTION () {return detail::numeric_limits<Rep>::lowest();}
};
} // namespace chrono
//----------------------------------------------------------------------------//
// 20.9.2.3 Specializations of common_type [time.traits.specializations] //
//----------------------------------------------------------------------------//
template <class Rep1, class Period1, class Rep2, class Period2>
struct common_type<chrono::duration<Rep1, Period1>,
chrono::duration<Rep2, Period2> >
{
typedef chrono::duration<typename common_type<Rep1, Rep2>::type,
typename boost::ratio_gcd<Period1, Period2>::type> type;
};
//----------------------------------------------------------------------------//
// //
// 20.9.3 Class template duration [time.duration] //
// //
//----------------------------------------------------------------------------//
namespace chrono {
template <class Rep, class Period>
class duration
{
BOOST_EX_CHRONO_STATIC_ASSERT(!boost_ex::chrono::detail::is_duration<Rep>::value, BOOST_EX_CHRONO_A_DURATION_REPRESENTATION_CAN_NOT_BE_A_DURATION, ());
BOOST_EX_CHRONO_STATIC_ASSERT(boost::ratio_detail::is_ratio<Period>::value, BOOST_EX_CHRONO_SECOND_TEMPLATE_PARAMETER_OF_DURATION_MUST_BE_A_STD_RATIO, ());
BOOST_EX_CHRONO_STATIC_ASSERT(Period::num>0, BOOST_EX_CHRONO_DURATION_PERIOD_MUST_BE_POSITIVE, ());
public:
typedef Rep rep;
typedef Period period;
private:
rep rep_;
public:
duration() { } // = default;
template <class Rep2>
explicit duration(const Rep2& r,
typename boost::enable_if <
boost::mpl::and_ <
boost::is_convertible<Rep2, rep>,
boost::mpl::or_ <
treat_as_floating_point<rep>,
boost::mpl::and_ <
boost::mpl::not_ < treat_as_floating_point<rep> >,
boost::mpl::not_ < treat_as_floating_point<Rep2> >
>
>
>
>::type* = 0)
: rep_(r) { }
~duration() {} //= default;
duration(const duration& rhs) : rep_(rhs.rep_) {} // = default;
duration& operator=(const duration& rhs) // = default;
{
if (&rhs != this) rep_= rhs.rep_;
return *this;
}
// conversions
template <class Rep2, class Period2>
duration(const duration<Rep2, Period2>& d,
typename boost::enable_if <
boost::mpl::or_ <
treat_as_floating_point<rep>,
boost::mpl::and_ <
boost::mpl::bool_ < boost::ratio_divide<Period2, period>::type::den == 1>,
boost::mpl::not_ < treat_as_floating_point<Rep2> >
>
>
>::type* = 0)
#ifdef __GNUC__
// GCC 4.2.4 refused to accept a definition at this point,
// yet both VC++ 9.0 SP1 and Intel ia32 11.0 accepted the definition
// without complaint. VC++ 9.0 SP1 refused to accept a later definition,
// although that was fine with GCC 4.2.4 and Intel ia32 11.0. Thus we
// have to support both approaches.
;
#else
: rep_(duration_cast<duration>(d).count()) {}
#endif
// observer
rep count() const {return rep_;}
// arithmetic
duration operator+() const {return *this;}
duration operator-() const {return duration(-rep_);}
duration& operator++() {++rep_; return *this;}
duration operator++(int) {return duration(rep_++);}
duration& operator--() {--rep_; return *this;}
duration operator--(int) {return duration(rep_--);}
duration& operator+=(const duration& d) {rep_ += d.count(); return *this;}
duration& operator-=(const duration& d) {rep_ -= d.count(); return *this;}
duration& operator*=(const rep& rhs) {rep_ *= rhs; return *this;}
duration& operator/=(const rep& rhs) {rep_ /= rhs; return *this;}
duration& operator%=(const rep& rhs) {rep_ %= rhs; return *this;}
duration& operator%=(const duration& rhs) {rep_ %= rhs.count(); return *this;};
// 20.9.3.4 duration special values [time.duration.special]
static duration zero() {return duration(duration_values<rep>::zero());}
static duration min BOOST_PREVENT_MACRO_SUBSTITUTION () {return duration((duration_values<rep>::min)());}
static duration max BOOST_PREVENT_MACRO_SUBSTITUTION () {return duration((duration_values<rep>::max)());}
};
//----------------------------------------------------------------------------//
// 20.9.3.5 duration non-member arithmetic [time.duration.nonmember] //
//----------------------------------------------------------------------------//
// Duration +
template <class Rep1, class Period1, class Rep2, class Period2>
inline
typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
operator+(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
{
typename common_type<duration<Rep1, Period1>,
duration<Rep2, Period2> >::type result = lhs;
result += rhs;
return result;
}
// Duration -
template <class Rep1, class Period1, class Rep2, class Period2>
inline
typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
operator-(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
{
typename common_type<duration<Rep1, Period1>,
duration<Rep2, Period2> >::type result = lhs;
result -= rhs;
return result;
}
// Duration *
template <class Rep1, class Period, class Rep2>
inline
typename boost::enable_if <
boost::mpl::and_ <
boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>,
boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>
>,
duration<typename common_type<Rep1, Rep2>::type, Period>
>::type
operator*(const duration<Rep1, Period>& d, const Rep2& s)
{
typedef typename common_type<Rep1, Rep2>::type CR;
duration<CR, Period> r = d;
r *= static_cast<CR>(s);
return r;
}
template <class Rep1, class Period, class Rep2>
inline
typename boost::enable_if <
boost::mpl::and_ <
boost::is_convertible<Rep1, typename common_type<Rep1, Rep2>::type>,
boost::is_convertible<Rep2, typename common_type<Rep1, Rep2>::type>
>,
duration<typename common_type<Rep1, Rep2>::type, Period>
>::type
operator*(const Rep1& s, const duration<Rep2, Period>& d)
{
return d * s;
}
// Duration /
template <class Rep1, class Period, class Rep2>
inline
typename boost::disable_if <boost_ex::chrono::detail::is_duration<Rep2>,
typename boost_ex::chrono::detail::duration_divide_result<duration<Rep1, Period>, Rep2>::type
>::type
operator/(const duration<Rep1, Period>& d, const Rep2& s)
{
typedef typename common_type<Rep1, Rep2>::type CR;
duration<CR, Period> r = d;
r /= static_cast<CR>(s);
return r;
}
template <class Rep1, class Period1, class Rep2, class Period2>
inline
typename common_type<Rep1, Rep2>::type
operator/(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
{
typedef typename common_type<duration<Rep1, Period1>,
duration<Rep2, Period2> >::type CD;
return CD(lhs).count() / CD(rhs).count();
}
template <class Rep1, class Rep2, class Period>
inline
typename boost::disable_if <boost_ex::chrono::detail::is_duration<Rep1>,
typename boost_ex::chrono::detail::duration_divide_result2<Rep1, duration<Rep2, Period> >::type
>::type
operator/(const Rep1& s, const duration<Rep2, Period>& d)
{
typedef typename common_type<Rep1, Rep2>::type CR;
duration<CR, Period> r = d;
//return static_cast<CR>(r.count()) / static_cast<CR>(s);
return static_cast<CR>(s)/r.count();
}
// Duration %
template <class Rep1, class Period, class Rep2>
typename boost::disable_if <boost_ex::chrono::detail::is_duration<Rep2>,
typename boost_ex::chrono::detail::duration_modulo_result<duration<Rep1, Period>, Rep2>::type
>::type
operator%(const duration<Rep1, Period>& d, const Rep2& s) {
typedef typename common_type<Rep1, Rep2>::type CR;
duration<CR, Period> r = d;
r %= static_cast<CR>(s);
return r;
}
template <class Rep1, class Period1, class Rep2, class Period2>
typename common_type<duration<Rep1, Period1>, duration<Rep2, Period2> >::type
operator%(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs) {
typedef typename common_type<duration<Rep1, Period1>,
duration<Rep2, Period2> >::type CD;
CD r(lhs);
r%=CD(rhs);
return r;
}
//----------------------------------------------------------------------------//
// 20.9.3.6 duration comparisons [time.duration.comparisons] //
//----------------------------------------------------------------------------//
namespace detail
{
template <class LhsDuration, class RhsDuration>
struct duration_eq
{
bool operator()(const LhsDuration& lhs, const RhsDuration& rhs)
{
typedef typename common_type<LhsDuration, RhsDuration>::type CD;
return CD(lhs).count() == CD(rhs).count();
}
};
template <class LhsDuration>
struct duration_eq<LhsDuration, LhsDuration>
{
bool operator()(const LhsDuration& lhs, const LhsDuration& rhs)
{return lhs.count() == rhs.count();}
};
template <class LhsDuration, class RhsDuration>
struct duration_lt
{
bool operator()(const LhsDuration& lhs, const RhsDuration& rhs)
{
typedef typename common_type<LhsDuration, RhsDuration>::type CD;
return CD(lhs).count() < CD(rhs).count();
}
};
template <class LhsDuration>
struct duration_lt<LhsDuration, LhsDuration>
{
bool operator()(const LhsDuration& lhs, const LhsDuration& rhs)
{return lhs.count() < rhs.count();}
};
} // namespace detail
// Duration ==
template <class Rep1, class Period1, class Rep2, class Period2>
inline
bool
operator==(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
{
return boost_ex::chrono::detail::duration_eq<duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs);
}
// Duration !=
template <class Rep1, class Period1, class Rep2, class Period2>
inline
bool
operator!=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
{
return !(lhs == rhs);
}
// Duration <
template <class Rep1, class Period1, class Rep2, class Period2>
inline
bool
operator< (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
{
return boost_ex::chrono::detail::duration_lt<duration<Rep1, Period1>, duration<Rep2, Period2> >()(lhs, rhs);
}
// Duration >
template <class Rep1, class Period1, class Rep2, class Period2>
inline
bool
operator> (const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
{
return rhs < lhs;
}
// Duration <=
template <class Rep1, class Period1, class Rep2, class Period2>
inline
bool
operator<=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
{
return !(rhs < lhs);
}
// Duration >=
template <class Rep1, class Period1, class Rep2, class Period2>
inline
bool
operator>=(const duration<Rep1, Period1>& lhs, const duration<Rep2, Period2>& rhs)
{
return !(lhs < rhs);
}
//----------------------------------------------------------------------------//
// 20.9.3.7 duration_cast [time.duration.cast] //
//----------------------------------------------------------------------------//
// Compile-time select the most efficient algorithm for the conversion...
template <class ToDuration, class Rep, class Period>
inline
typename boost::enable_if <boost_ex::chrono::detail::is_duration<ToDuration>, ToDuration>::type
duration_cast(const duration<Rep, Period>& fd)
{
return boost_ex::chrono::detail::duration_cast<duration<Rep, Period>, ToDuration>()(fd);
}
//----------------------------------------------------------------------------//
// duration constructor implementation //
// See comment in the class duration synopsis //
//----------------------------------------------------------------------------//
#ifdef __GNUC__
// see comment above in section 20.9.3 Class template duration [time.duration]
template <class Rep, class Period>
template <class Rep2, class Period2>
duration<Rep, Period>::duration(const duration<Rep2, Period2>& d,
typename boost::enable_if <
boost::mpl::or_ <
treat_as_floating_point<rep>,
boost::mpl::and_ <
boost::mpl::bool_ <boost::ratio_divide<Period2, period>::type::den == 1>,
boost::mpl::not_ <treat_as_floating_point<Rep2> >
>
>
>::type*)
: rep_(duration_cast<duration>(d).count()) {}
#endif
}
}
#endif // BOOST_EX_CHRONO_DURATION_HPP

236
example/si_physics.cpp Normal file
View File

@ -0,0 +1,236 @@
// ratio_test.cpp ----------------------------------------------------------//
// Copyright 2008 Howard Hinnant
// Copyright 2008 Beman Dawes
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
#include <iostream>
#include <boost/ratio.hpp>
#include "duration.hpp"
namespace User1
{
// Example type-safe "physics" code interoperating with chrono::duration types
// and taking advantage of the std::ratio infrastructure and design philosophy.
// length - mimics chrono::duration except restricts representation to double.
// Uses boost::ratio facilities for length units conversions.
template <class Ratio>
class length
{
public:
typedef Ratio ratio;
private:
double len_;
public:
length() : len_(1) {}
length(const double& len) : len_(len) {}
// conversions
template <class R>
length(const length<R>& d)
: len_(d.count() * boost::ratio_divide<Ratio, R>::type::den /
boost::ratio_divide<Ratio, R>::type::num) {}
// observer
double count() const {return len_;}
// arithmetic
length& operator+=(const length& d) {len_ += d.count(); return *this;}
length& operator-=(const length& d) {len_ -= d.count(); return *this;}
length operator+() const {return *this;}
length operator-() const {return length(-len_);}
length& operator*=(double rhs) {len_ *= rhs; return *this;}
length& operator/=(double rhs) {len_ /= rhs; return *this;}
};
// Sparse sampling of length units
typedef length<boost::ratio<1> > meter; // set meter as "unity"
typedef length<boost::centi> centimeter; // 1/100 meter
typedef length<boost::kilo> kilometer; // 1000 meters
typedef length<boost::ratio<254, 10000> > inch; // 254/10000 meters
// length takes ratio instead of two integral types so that definitions can be made like so:
typedef length<boost::ratio_multiply<boost::ratio<12>, inch::ratio>::type> foot; // 12 inchs
typedef length<boost::ratio_multiply<boost::ratio<5280>, foot::ratio>::type> mile; // 5280 feet
// Need a floating point definition of seconds
typedef boost_ex::chrono::duration<double> seconds; // unity
// Demo of (scientific) support for sub-nanosecond resolutions
typedef boost_ex::chrono::duration<double, boost::pico> picosecond; // 10^-12 seconds
typedef boost_ex::chrono::duration<double, boost::femto> femtosecond; // 10^-15 seconds
typedef boost_ex::chrono::duration<double, boost::atto> attosecond; // 10^-18 seconds
// A very brief proof-of-concept for SIUnits-like library
// Hard-wired to floating point seconds and meters, but accepts other units (shown in testUser1())
template <class R1, class R2>
class quantity
{
double q_;
public:
typedef R1 time_dim;
typedef R2 distance_dim;
quantity() : q_(1) {}
double get() const {return q_;}
void set(double q) {q_ = q;}
};
template <>
class quantity<boost::ratio<1>, boost::ratio<0> >
{
double q_;
public:
quantity() : q_(1) {}
quantity(seconds d) : q_(d.count()) {} // note: only User1::seconds needed here
double get() const {return q_;}
void set(double q) {q_ = q;}
};
template <>
class quantity<boost::ratio<0>, boost::ratio<1> >
{
double q_;
public:
quantity() : q_(1) {}
quantity(meter d) : q_(d.count()) {} // note: only User1::meter needed here
double get() const {return q_;}
void set(double q) {q_ = q;}
};
template <>
class quantity<boost::ratio<0>, boost::ratio<0> >
{
double q_;
public:
quantity() : q_(1) {}
quantity(double d) : q_(d) {}
double get() const {return q_;}
void set(double q) {q_ = q;}
};
// Example SI-Units
typedef quantity<boost::ratio<0>, boost::ratio<0> > Scalar;
typedef quantity<boost::ratio<1>, boost::ratio<0> > Time; // second
typedef quantity<boost::ratio<0>, boost::ratio<1> > Distance; // meter
typedef quantity<boost::ratio<-1>, boost::ratio<1> > Speed; // meter/second
typedef quantity<boost::ratio<-2>, boost::ratio<1> > Acceleration; // meter/second^2
template <class R1, class R2, class R3, class R4>
quantity<typename boost::ratio_subtract<R1, R3>::type, typename boost::ratio_subtract<R2, R4>::type>
operator/(const quantity<R1, R2>& x, const quantity<R3, R4>& y)
{
typedef quantity<typename boost::ratio_subtract<R1, R3>::type, typename boost::ratio_subtract<R2, R4>::type> R;
R r;
r.set(x.get() / y.get());
return r;
}
template <class R1, class R2, class R3, class R4>
quantity<typename boost::ratio_add<R1, R3>::type, typename boost::ratio_add<R2, R4>::type>
operator*(const quantity<R1, R2>& x, const quantity<R3, R4>& y)
{
typedef quantity<typename boost::ratio_add<R1, R3>::type, typename boost::ratio_add<R2, R4>::type> R;
R r;
r.set(x.get() * y.get());
return r;
}
template <class R1, class R2>
quantity<R1, R2>
operator+(const quantity<R1, R2>& x, const quantity<R1, R2>& y)
{
typedef quantity<R1, R2> R;
R r;
r.set(x.get() + y.get());
return r;
}
template <class R1, class R2>
quantity<R1, R2>
operator-(const quantity<R1, R2>& x, const quantity<R1, R2>& y)
{
typedef quantity<R1, R2> R;
R r;
r.set(x.get() - y.get());
return r;
}
// Example type-safe physics function
Distance
compute_distance(Speed v0, Time t, Acceleration a)
{
return v0 * t + Scalar(.5) * a * t * t; // if a units mistake is made here it won't compile
}
} // User1
// Exercise example type-safe physics function and show interoperation
// of custom time durations (User1::seconds) and standard time durations (std::hours).
// Though input can be arbitrary (but type-safe) units, output is always in SI-units
// (a limitation of the simplified Units lib demoed here).
int main()
{
//~ typedef boost::ratio<8, BOOST_INTMAX_C(0x7FFFFFFFD)> R1;
//~ typedef boost::ratio<3, BOOST_INTMAX_C(0x7FFFFFFFD)> R2;
typedef User1::quantity<boost::ratio_subtract<boost::ratio<0>, boost::ratio<1> >::type,
boost::ratio_subtract<boost::ratio<1>, boost::ratio<0> >::type > RR;
//~ typedef boost::ratio_subtract<R1, R2>::type RS;
//~ std::cout << RS::num << '/' << RS::den << '\n';
std::cout << "*************\n";
std::cout << "* testUser1 *\n";
std::cout << "*************\n";
User1::Distance d(( User1::mile(110) ));
boost_ex::chrono::hours h((2));
User1::Time t(( h ));
//~ boost_ex::chrono::seconds sss=boost_ex::chrono::duration_cast<boost_ex::chrono::seconds>(h);
//~ User1::seconds sss((120));
//~ User1::Time t(( sss ));
//typedef User1::quantity<boost::ratio_subtract<User1::Distance::time_dim, User1::Time::time_dim >::type,
// boost::ratio_subtract<User1::Distance::distance_dim, User1::Time::distance_dim >::type > R;
RR r=d / t;
//r.set(d.get() / t.get());
User1::Speed rc= r;
User1::Speed s = d / t;
std::cout << "Speed = " << s.get() << " meters/sec\n";
User1::Acceleration a = User1::Distance( User1::foot(32.2) ) / User1::Time() / User1::Time();
std::cout << "Acceleration = " << a.get() << " meters/sec^2\n";
User1::Distance df = compute_distance(s, User1::Time( User1::seconds(0.5) ), a);
std::cout << "Distance = " << df.get() << " meters\n";
std::cout << "There are " << User1::mile::ratio::den << '/' << User1::mile::ratio::num << " miles/meter";
User1::meter mt = 1;
User1::mile mi = mt;
std::cout << " which is approximately " << mi.count() << '\n';
std::cout << "There are " << User1::mile::ratio::num << '/' << User1::mile::ratio::den << " meters/mile";
mi = 1;
mt = mi;
std::cout << " which is approximately " << mt.count() << '\n';
User1::attosecond as(1);
User1::seconds sec = as;
std::cout << "1 attosecond is " << sec.count() << " seconds\n";
std::cout << "sec = as; // compiles\n";
sec = User1::seconds(1);
as = sec;
std::cout << "1 second is " << as.count() << " attoseconds\n";
std::cout << "as = sec; // compiles\n";
std::cout << "\n";
return 0;
}

30
example/static_assert.hpp Normal file
View File

@ -0,0 +1,30 @@
// static_assert.hpp --------------------------------------------------------------//
// Copyright 2009-2010 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_EX_CHRONO_DETAIL_STATIC_ASSERT_HPP
#define BOOST_EX_CHRONO_DETAIL_STATIC_ASSERT_HPP
#include "config.hpp"
#ifndef BOOST_NO_STATIC_ASSERT
#define BOOST_EX_CHRONO_STATIC_ASSERT(CND, MSG, TYPES) static_assert(CND,MSG)
#elif defined(BOOST_CHRONO_USES_STATIC_ASSERT)
#include <boost/static_assert.hpp>
#define BOOST_EX_CHRONO_STATIC_ASSERT(CND, MSG, TYPES) BOOST_STATIC_ASSERT(CND)
#elif defined(BOOST_CHRONO_USES_MPL_ASSERT)
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
#define BOOST_EX_CHRONO_STATIC_ASSERT(CND, MSG, TYPES) \
BOOST_MPL_ASSERT_MSG(boost::mpl::bool_< (CND) >::type::value, MSG, TYPES)
#else
//~ #elif defined(BOOST_CHRONO_USES_ARRAY_ASSERT)
#define BOOST_EX_CHRONO_STATIC_ASSERT(CND, MSG, TYPES) static char BOOST_JOIN(boost_chrono_test_,__LINE__)[(CND)?1:-1]
//~ #define BOOST_EX_CHRONO_STATIC_ASSERT(CND, MSG, TYPES)
#endif
#endif // BOOST_EX_CHRONO_DETAIL_STATIC_ASSERT_HPP

View File

@ -0,0 +1,67 @@
// add_rvalue_reference.hpp ---------------------------------------------------------//
// Copyright 2010 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_EX_TYPE_TRAITS_EXT_ADD_RVALUE_REFERENCE__HPP
#define BOOST_EX_TYPE_TRAITS_EXT_ADD_RVALUE_REFERENCE__HPP
#include <boost/config.hpp>
//----------------------------------------------------------------------------//
#include <boost/type_traits/is_void.hpp>
#include <boost/type_traits/is_reference.hpp>
// should be the last #include
#include <boost/type_traits/detail/type_trait_def.hpp>
//----------------------------------------------------------------------------//
// //
// C++03 implementation of //
// 20.7.6.2 Reference modifications [meta.trans.ref] //
// Written by Vicente J. Botet Escriba //
// //
// If T names an object or function type then the member typedef type
// shall name T&&; otherwise, type shall name T. [ Note: This rule reflects
// the semantics of reference collapsing. For example, when a type T names
// a type T1&, the type add_rvalue_reference<T>::type is not an rvalue
// reference. -end note ]
//----------------------------------------------------------------------------//
namespace boost_ex {
namespace type_traits_detail {
template <typename T, bool b>
struct add_rvalue_reference_helper
{ typedef T type; };
template <typename T>
struct add_rvalue_reference_helper<T, true>
{
#if !defined(BOOST_NO_RVALUE_REFERENCES)
typedef T&& type;
#else
typedef T type;
#endif
};
template <typename T>
struct add_rvalue_reference_imp
{
typedef typename boost_ex::type_traits_detail::add_rvalue_reference_helper
<T, (!boost::is_void<T>::value && !boost::is_reference<T>::value) >::type type;
};
}
BOOST_TT_AUX_TYPE_TRAIT_DEF1(add_rvalue_reference,T,typename boost_ex::type_traits_detail::add_rvalue_reference_imp<T>::type)
} // namespace boost_ex
#include <boost/type_traits/detail/type_trait_undef.hpp>
#endif // BOOST_EX_TYPE_TRAITS_EXT_ADD_RVALUE_REFERENCE__HPP

View File

@ -0,0 +1,151 @@
// common_type.hpp ---------------------------------------------------------//
// Copyright 2008 Howard Hinnant
// Copyright 2008 Beman Dawes
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_EX_TYPE_TRAITS_EXT_COMMON_TYPE_HPP
#define BOOST_EX_TYPE_TRAITS_EXT_COMMON_TYPE_HPP
#include <boost/config.hpp>
//----------------------------------------------------------------------------//
#if defined(BOOST_NO_VARIADIC_TEMPLATES)
#define BOOST_EX_COMMON_TYPE_ARITY 3
#endif
//----------------------------------------------------------------------------//
#if defined(BOOST_NO_DECLTYPE) && !defined(BOOST_EX_COMMON_TYPE_DONT_USE_TYPEOF)
#define BOOST_TYPEOF_SILENT
#include <boost/typeof/typeof.hpp> // boost wonders never cease!
#endif
//----------------------------------------------------------------------------//
#ifndef BOOST_NO_STATIC_ASSERT
#define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) static_assert(CND,MSG)
#elif defined(BOOST_EX_COMMON_TYPE_USES_STATIC_ASSERT)
#include <boost/static_assert.hpp>
#define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) BOOST_STATIC_ASSERT(CND)
#elif defined(BOOST_EX_COMMON_TYPE_USES_MPL_ASSERT)
#include <boost/mpl/assert.hpp>
#include <boost/mpl/bool.hpp>
#define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) \
BOOST_MPL_ASSERT_MSG(boost::mpl::bool_< (CND) >::type::value, MSG, TYPES)
#else
//~ #elif defined(BOOST_EX_COMMON_TYPE_USES_ARRAY_ASSERT)
#define BOOST_EX_COMMON_TYPE_CONCAT(A,B) A##B
#define BOOST_EX_COMMON_TYPE_NAME(A,B) BOOST_EX_COMMON_TYPE_CONCAT(A,B)
#define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES) static char BOOST_EX_COMMON_TYPE_NAME(__boost_common_type_test_,__LINE__)[(CND)?1:-1]
//~ #define BOOST_EX_COMMON_TYPE_STATIC_ASSERT(CND, MSG, TYPES)
#endif
#if !defined(BOOST_NO_STATIC_ASSERT) || !defined(BOOST_EX_COMMON_TYPE_USES_MPL_ASSERT)
#define BOOST_EX_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE "must be complete type"
#endif
#if defined(BOOST_NO_DECLTYPE) && defined(BOOST_EX_COMMON_TYPE_DONT_USE_TYPEOF)
#include "detail/common_type.hpp"
#include <boost/type_traits/remove_cv.hpp>
#endif
#include <boost/mpl/if.hpp>
#include "declval.hpp"
//----------------------------------------------------------------------------//
// //
// C++03 implementation of //
// 20.6.7 Other transformations [meta.trans.other] //
// Written by Howard Hinnant //
// Adapted for Boost by Beman Dawes, Vicente Botet and Jeffrey Hellrung //
// //
//----------------------------------------------------------------------------//
namespace boost_ex {
// prototype
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template<typename... T>
struct common_type;
#else // or no specialization
template <class T, class U = void, class V = void>
struct common_type
{
public:
typedef typename common_type<typename common_type<T, U>::type, V>::type type;
};
#endif
// 1 arg
template<typename T>
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
struct common_type<T>
#else
struct common_type<T, void, void>
#endif
{
BOOST_EX_COMMON_TYPE_STATIC_ASSERT(sizeof(T) > 0, BOOST_EX_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE, (T));
public:
typedef T type;
};
// 2 args
namespace type_traits_detail {
template <class T, class U>
struct common_type_2
{
private:
BOOST_EX_COMMON_TYPE_STATIC_ASSERT(sizeof(T) > 0, BOOST_EX_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE, (T));
BOOST_EX_COMMON_TYPE_STATIC_ASSERT(sizeof(U) > 0, BOOST_EX_COMMON_TYPE_MUST_BE_A_COMPLE_TYPE, (U));
static bool declval_bool(); // workaround gcc bug; not required by std
static typename add_rvalue_reference<T>::type declval_T(); // workaround gcc bug; not required by std
static typename add_rvalue_reference<U>::type declval_U(); // workaround gcc bug; not required by std
#if !defined(BOOST_NO_DECLTYPE)
public:
typedef decltype(declval<bool>() ? declval<T>() : declval<U>()) type;
#elif defined(BOOST_EX_COMMON_TYPE_DONT_USE_TYPEOF)
public:
typedef typename detail_type_traits_common_type::common_type_impl<
typename remove_cv<T>::type,
typename remove_cv<U>::type
>::type type;
#else
public:
//~ typedef BOOST_TYPEOF_TPL(declval_bool() ? declval_T() : declval_U()) type;
typedef BOOST_TYPEOF_TPL(declval<bool>() ? declval<T>() : declval<U>()) type;
#endif
};
template <class T>
struct common_type_2<T, T>
{
typedef T type;
};
}
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template <class T, class U>
struct common_type<T, U>
#else
template <class T, class U>
struct common_type<T, U, void>
#endif
: type_traits_detail::common_type_2<T,U>
{ };
// 3 or more args
#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
template<typename T, typename U, typename... V>
struct common_type<T, U, V...> {
public:
typedef typename common_type<typename common_type<T, U>::type, V...>::type type;
};
#endif
} // namespace boost_ex
#endif // BOOST_TYPE_TRAITS_EXT_COMMON_TYPE_HPP

View File

@ -0,0 +1,44 @@
// common_type.hpp ---------------------------------------------------------//
// Copyright 2010 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
#ifndef BOOST_EX_TYPE_TRAITS_EXT_DECLVAL__HPP
#define BOOST_EX_TYPE_TRAITS_EXT_DECLVAL__HPP
#include <boost/config.hpp>
//----------------------------------------------------------------------------//
#include "add_rvalue_reference.hpp"
//----------------------------------------------------------------------------//
// //
// C++03 implementation of //
// Written by Vicente J. Botet Escriba //
//~ 20.3.4 Function template declval [declval]
//~ 1 The library provides the function template declval to simplify the definition of expressions which occur as
//~ unevaluated operands.
//~ 2 Remarks: If this function is used, the program is ill-formed.
//~ 3 Remarks: The template parameter T of declval may be an incomplete type.
//~ [ Example:
//~ template <class To, class From>
//~ decltype(static_cast<To>(declval<From>())) convert(From&&);
//~ declares a function template convert which only participats in overloading if the type From can be
//~ explicitly converted to type To. For another example see class template common_type (20.7.6.6). -end
//~ example ]
// //
//----------------------------------------------------------------------------//
namespace boost_ex {
template <typename T>
typename add_rvalue_reference<T>::type declval(); //noexcept; // as unevaluated operand
} // namespace boost
#endif // BOOST_EX_TYPE_TRAITS_EXT_DECLVAL__HPP

View File

@ -0,0 +1,316 @@
/*******************************************************************************
* boost/type_traits/detail/common_type.hpp
*
* Copyright 2010, Jeffrey Hellrung.
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*
* struct boost::common_type<T,U>
*
* common_type<T,U>::type is the type of the expression
* b() ? x() : y()
* where b() returns a bool, x() has return type T, and y() has return type U.
* See
* http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2661.htm#common_type
*
* Note that this evaluates to void if one or both of T and U is void.
******************************************************************************/
#ifndef BOOST_EX_TYPE_TRAITS_EXT_DETAIL_COMMON_TYPE_HPP
#define BOOST_EX_TYPE_TRAITS_EXT_DETAIL_COMMON_TYPE_HPP
#include <cstddef>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/begin_end.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/inserter.hpp>
#include <boost/mpl/next.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/push_back.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/vector/vector0.hpp>
#include <boost/mpl/vector/vector10.hpp>
#include <boost/type_traits/integral_constant.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/make_signed.hpp>
#include <boost/type_traits/make_unsigned.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/declval.hpp>
namespace boost_ex
{
namespace detail_type_traits_common_type
{
/*******************************************************************************
* struct propagate_cv< From, To >
*
* This metafunction propagates cv-qualifiers on type From to type To.
******************************************************************************/
template< class From, class To >
struct propagate_cv
{ typedef To type; };
template< class From, class To >
struct propagate_cv< const From, To >
{ typedef To const type; };
template< class From, class To >
struct propagate_cv< volatile From, To >
{ typedef To volatile type; };
template< class From, class To >
struct propagate_cv< const volatile From, To >
{ typedef To const volatile type; };
/*******************************************************************************
* struct is_signable_integral<T>
*
* This metafunction determines if T is an integral type which can be made
* signed or unsigned.
******************************************************************************/
template< class T >
struct is_signable_integral
: mpl::or_< is_integral<T>, is_enum<T> >
{ };
template<>
struct is_signable_integral< bool >
: false_type
{ };
/*******************************************************************************
* struct sizeof_t<N>
* typedef ... yes_type
* typedef ... no_type
*
* These types are integral players in the use of the "sizeof trick", i.e., we
* can distinguish overload selection by inspecting the size of the return type
* of the overload.
******************************************************************************/
template< std::size_t N > struct sizeof_t { char _dummy[N]; };
typedef sizeof_t<1> yes_type;
typedef sizeof_t<2> no_type;
BOOST_MPL_ASSERT_RELATION( sizeof( yes_type ), ==, 1 );
BOOST_MPL_ASSERT_RELATION( sizeof( no_type ), ==, 2 );
/*******************************************************************************
* rvalue_test(T&) -> no_type
* rvalue_test(...) -> yes_type
*
* These overloads are used to determine the rvalue-ness of an expression.
******************************************************************************/
template< class T > no_type rvalue_test(T&);
yes_type rvalue_test(...);
/*******************************************************************************
* struct conversion_test_overloads< Sequence >
*
* This struct has multiple overloads of the static member function apply, each
* one taking a single parameter of a type within the Boost.MPL sequence
* Sequence. Each such apply overload has a return type with sizeof equal to
* one plus the index of the parameter type within Sequence. Thus, we can
* deduce the type T of an expression as long as we can generate a finite set of
* candidate types containing T via these apply overloads and the "sizeof
* trick".
******************************************************************************/
template< class First, class Last, std::size_t Index >
struct conversion_test_overloads_iterate
: conversion_test_overloads_iterate<
typename mpl::next< First >::type, Last, Index + 1
>
{
using conversion_test_overloads_iterate<
typename mpl::next< First >::type, Last, Index + 1
>::apply;
static sizeof_t< Index + 1 >
apply(typename mpl::deref< First >::type);
};
template< class Last, std::size_t Index >
struct conversion_test_overloads_iterate< Last, Last, Index >
{ static sizeof_t< Index + 1 > apply(...); };
template< class Sequence >
struct conversion_test_overloads
: conversion_test_overloads_iterate<
typename mpl::begin< Sequence >::type,
typename mpl::end< Sequence >::type,
0
>
{ };
/*******************************************************************************
* struct select< Sequence, Index >
*
* select is synonymous with mpl::at_c unless Index equals the size of the
* Boost.MPL Sequence, in which case this evaluates to void.
******************************************************************************/
template<
class Sequence, int Index,
int N = mpl::size< Sequence >::value
>
struct select
: mpl::at_c< Sequence, Index >
{ };
template< class Sequence, int N >
struct select< Sequence, N, N >
{ typedef void type; };
/*******************************************************************************
* class deduce_common_type< T, U, NominalCandidates >
* struct nominal_candidates<T,U>
* struct common_type_dispatch_on_rvalueness<T,U>
* struct common_type_impl<T,U>
*
* These classes and structs implement the logic behind common_type, which goes
* roughly as follows. Let C be the type of the conditional expression
* declval< bool >() ? declval<T>() : declval<U>()
* if C is an rvalue, then:
* let T' and U' be T and U stripped of reference- and cv-qualifiers
* if T' and U' are pointer types, say, T' = V* and U' = W*, then:
* define the set of NominalCandidates to be
* { V*, W*, V'*, W'* }
* where V' is V with whatever cv-qualifiers are on W, and W' is W
* with whatever cv-qualifiers are on V
* else T' and U' are both "signable integral types" (integral and enum
* types excepting bool), then:
* define the set of NominalCandidates to be
* { unsigned(T'), unsigned(U'), signed(T'), signed(U') }
* where unsigned(X) is make_unsigned<X>::type and signed(X) is
* make_signed<X>::type
* else
* define the set of NominalCandidates to be
* { T', U' }
* else
* let V and W be T and U stripped of reference-qualifiers
* define the set of NominalCandidates to be
* { V&, W&, V'&, W'& }
* where V' is V with whatever cv-qualifiers are on W, and W' is W with
* whatever cv-qualifiers are on V
* define the set of Candidates to be equal to the set of NominalCandidates with
* duplicates removed, and use this set of Candidates to determine C using the
* conversion_test_overloads struct
******************************************************************************/
template< class T, class U, class NominalCandidates >
class deduce_common_type
{
typedef typename mpl::copy<
NominalCandidates,
mpl::inserter<
mpl::vector0<>,
mpl::if_<
mpl::contains< mpl::_1, mpl::_2 >,
mpl::_1,
mpl::push_back< mpl::_1, mpl::_2 >
>
>
>::type candidate_types;
static const int best_candidate_index =
sizeof( conversion_test_overloads< candidate_types >::apply(
declval< bool >() ? declval<T>() : declval<U>()
) ) - 1;
public:
typedef typename select< candidate_types, best_candidate_index >::type type;
};
template<
class T, class U,
class V = typename remove_cv< typename remove_reference<T>::type >::type,
class W = typename remove_cv< typename remove_reference<U>::type >::type,
bool = is_signable_integral<V>::value && is_signable_integral<W>::value
>
struct nominal_candidates;
template< class T, class U, class V, class W >
struct nominal_candidates< T, U, V, W, false >
{ typedef mpl::vector2<V,W> type; };
template< class T, class U, class V, class W >
struct nominal_candidates< T, U, V, W, true >
{
typedef mpl::vector4<
typename make_unsigned<V>::type,
typename make_unsigned<W>::type,
typename make_signed<V>::type,
typename make_signed<W>::type
> type;
};
template< class T, class U, class V, class W >
struct nominal_candidates< T, U, V*, W*, false >
{
typedef mpl::vector4<
V*, W*,
typename propagate_cv<W,V>::type *,
typename propagate_cv<V,W>::type *
> type;
};
template<
class T, class U,
bool = sizeof( ::boost::detail_type_traits_common_type::rvalue_test(
declval< bool >() ? declval<T>() : declval<U>()
) ) == sizeof( yes_type )
>
struct common_type_dispatch_on_rvalueness;
template< class T, class U >
struct common_type_dispatch_on_rvalueness< T, U, true >
: deduce_common_type< T, U, typename nominal_candidates<T,U>::type >
{ };
template< class T, class U >
struct common_type_dispatch_on_rvalueness< T, U, false >
{
private:
typedef typename remove_reference<T>::type unrefed_T_type;
typedef typename remove_reference<U>::type unrefed_U_type;
public:
typedef typename deduce_common_type<
T, U,
mpl::vector4<
unrefed_T_type &,
unrefed_U_type &,
typename propagate_cv< unrefed_U_type, unrefed_T_type >::type &,
typename propagate_cv< unrefed_T_type, unrefed_U_type >::type &
>
>::type type;
};
template< class T, class U >
struct common_type_impl
: common_type_dispatch_on_rvalueness<T,U>
{ };
template< class T > struct common_type_impl< T, void > { typedef void type; };
template< class T > struct common_type_impl< void, T > { typedef void type; };
template<> struct common_type_impl< void, void > { typedef void type; };
template< > struct common_type_impl< char, short> { typedef int type; };
template< > struct common_type_impl< short, char> { typedef int type; };
template< > struct common_type_impl< unsigned char, short> { typedef int type; };
template< > struct common_type_impl< short, unsigned char> { typedef int type; };
template< > struct common_type_impl< unsigned char, unsigned short> { typedef int type; };
template< > struct common_type_impl< unsigned short, unsigned char> { typedef int type; };
template< > struct common_type_impl< char, unsigned short> { typedef int type; };
template< > struct common_type_impl< unsigned short, char> { typedef int type; };
} // namespace detail_type_traits_common_type
} // namespace boost_ex
#endif // BOOST_EX_TYPE_TRAITS_EXT_DETAIL_COMMON_TYPE_HPP