mirror of
https://github.com/boostorg/ratio.git
synced 2025-05-09 23:24:01 +00:00
Boost.Ratio: moved to trunk
[SVN r67575]
This commit is contained in:
parent
88da98e37b
commit
3ac9309817
73
doc/Jamfile.v2
Normal file
73
doc/Jamfile.v2
Normal 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
15
doc/index.html
Normal 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>© Copyright 2009-2010 Vicente J. Botet Escribá.
|
||||
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
6740
doc/ratio.pdf
Normal file
File diff suppressed because it is too large
Load Diff
1256
doc/ratio.qbk
Normal file
1256
doc/ratio.qbk
Normal file
File diff suppressed because it is too large
Load Diff
123
example/config.hpp
Normal file
123
example/config.hpp
Normal 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
39
example/display_ex.cpp
Normal 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
793
example/duration.hpp
Normal 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
236
example/si_physics.cpp
Normal 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
30
example/static_assert.hpp
Normal 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
|
67
example/type_traits/add_rvalue_reference.hpp
Normal file
67
example/type_traits/add_rvalue_reference.hpp
Normal 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
|
151
example/type_traits/common_type.hpp
Normal file
151
example/type_traits/common_type.hpp
Normal 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
|
44
example/type_traits/declval.hpp
Normal file
44
example/type_traits/declval.hpp
Normal 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
|
316
example/type_traits/detail/common_type.hpp
Normal file
316
example/type_traits/detail/common_type.hpp
Normal 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
|
Loading…
x
Reference in New Issue
Block a user