Compare commits

...

70 Commits

Author SHA1 Message Date
792d0538d2 Merge branch 'develop' 2017-07-17 20:47:57 +03:00
06ae661775 Merge pull request #31 from Lastique/next_prior_use_traversal
Use Boost.Iterator to advance iterators.
2017-07-13 21:04:18 +03:00
d9d076874e Merge branch 'develop' 2017-07-13 20:59:28 +03:00
e25d85446e Use Boost.Iterator to advance iterators.
By using Boost.Iterator we rely on the separate traversal category instead of
the standard iterator category to advance iterators efficiently. For instance,
this allows to advance transform iterators over a random access sequence
in constant time, despite that they are formally input iterators.

Also, std::reverse_iterator formally requires at least bidirectional iterator
as the underlying iterator type. Transform iterators from the example above
don't qualify, so potentially std::reverse_iterator could fail to compile.
2017-07-12 21:15:20 +03:00
5bc9e47688 Changed iterator_category nested type detection to work with MSVC and different versions of gcc. 2017-07-12 20:14:48 +03:00
ec50f22b8b Merge pull request #30 from Lastique/fix_next_prior_for_iterators
Fix next/prior for iterators
2017-07-09 13:41:03 +03:00
592382dc61 Add test cases for std::reverse_iterator 2017-07-09 03:10:10 +03:00
6cf9c22cf1 Reworked iterator handling in next/prior helpers.
The new implementation tries to detect if the incremented/decremented type
is an iterator first and if not falls back to operator probing. This way
iterators that are not SFINAE-friendly (i.e. unconditionally define
arithmetic operators regardless of the iterator category) are still treated
as iterators through std::advance and do not fail the compilation.

The iterator detection is based on probing for the nested iterator_category
type that is expected to be present in class-type iterators. This heuristic
is not flawless since iterators are not required to defined this type.
User-defined iterators may not have it and instead specialize
std::iterator_traits. This use case is not covered by the current implementation
and will likely fail to compile. With C++17 SFINAE-friendly std::iterator_traits
this can be fixed, but currently Boost.Config lacks the macro to detect
availability of this feature. Support for it can be added by a later commit.

Also simplified boost::prior for iterators, removing the possibility of
integer overflow caused by negation of the distance value.
2017-07-09 03:10:01 +03:00
33475f87e4 Merge branch 'develop' 2017-05-30 15:08:09 +03:00
21261a8630 Add visible dependency to result_of_iterate.hpp 2017-05-30 01:20:02 +03:00
7d60e8e378 Merge branch 'develop' 2017-05-30 00:56:41 +03:00
10ff4d4fcd Try to upgrade libstdc++ for clang in 14/1z mode 2017-05-29 21:27:57 +03:00
89bf74beee Add .travis.yml 2017-05-29 19:16:28 +03:00
bfdcce0f97 Move test files to test/ 2017-05-29 19:10:46 +03:00
330b49d602 Mark comparison operators for string_view as constexpr; add tests. Reference: https://svn.boost.org/trac/boost/ticket/12896 2017-05-03 19:58:02 -07:00
68b26cddbe Merge branch 'develop' of github.com:boostorg/utility into develop 2017-04-06 07:59:12 -07:00
6c4ab93573 Revert change disallowing construction of string_view/string_ref from rvalue string 2017-03-28 15:17:09 +02:00
0876da45db Fix potential overflow in substr; Trac #11536. Also change string_view::copy to use the traits::copy 2017-02-13 10:49:17 -08:00
00f02167e3 Add tests to ensure that string_view|ref from rvalue fails (whenever it can) 2017-02-13 10:25:04 -08:00
9960d9f395 Don't construct string_view|string_ref from rvalue string. That way lies pain 2017-02-13 08:15:44 -08:00
ccfd741c0a Merge pull request #27 from MarcelRaad/patch-1
Use non-deprecated include paths
2016-12-21 12:20:20 +04:00
c5c479d49c Use non-deprecated include paths
According to the comments in these two headers, the files in the core directory should be used instead.
2016-12-21 08:22:35 +01:00
3e8f73c6ac Merge pull request #26 from Surrog/develop
Fixing visual studio compilation of string_view::at(); preserving C++11 constexpr-ness.
2016-12-12 17:22:29 -08:00
38121f2af3 Allow string_view::at() to be constexpr again on VS2015
VS2015 doesn't support extended constexpr. Thanks to Lastique for the
ternary trick
2016-12-12 23:45:34 +01:00
38b536ff05 Fixing visual studio compilation of string_view::at()
VS2013, VS2015 & VS2017RC don't like the ternary throwing an exception :
'return': cannot convert from 'void' to 'const char &'
Now using classic if when compiling on a windows platform.
2016-12-12 22:57:56 +01:00
9ae6492af9 Merge pull request #25 from zerotypos-found/inspection_report
Remove tabs and Non-ASCII characters.  Thanks!
2016-11-21 18:25:08 -08:00
816607e212 Remove tabs and Non-ASCII characters. 2016-11-15 11:59:51 +09:00
a3ab942bc2 Merge branch 'develop' 2016-11-08 16:56:27 +03:00
0f1f793caf Removed std::binary_function from a comment. 2016-11-06 21:18:27 +03:00
ff445c0ece Remove std::binary_function use, it has been removed in C++17 2016-11-06 14:38:13 +02:00
9fae8be166 Add, and update, documentation build targets. 2016-10-10 11:39:54 -05:00
b90a28f0e1 Add, and update, documentation build targets. 2016-10-07 23:07:37 -05:00
febca584d9 Removed -u command line option for the compressed_pair_test as this option is not recognized by Boost.Test (and presumably never was). This fixes the test execution failure. 2016-09-03 00:25:51 +03:00
21dc552cf9 Added a workaround for gcc 4.6 in C++11 mode as it can't seem to handle defaulted functions with noexcept specifier. The problem was discovered with autotests. 2016-09-02 19:14:00 +03:00
fda210f597 Merge branch 'develop' 2016-09-02 18:34:58 +03:00
3d853b0e83 Reworked to_string test to verify the overload with a custom allocator even when explicit conversion operators are not supported. Made the custom allocator more standard-compliant. 2016-09-01 22:42:29 +03:00
4814d1ebfe Added another overload of to_string when default function template arguments are not supported.
The additional overload more closely emulates the official interface and allows to construct strings with custom allocators.
2016-09-01 22:08:28 +03:00
e5932ebb08 fix compile error on basic_string_view::to_string when Allocator is user-defined 2016-09-01 21:56:20 +03:00
93a2e25092 Merge to master for 1.62.0 release 2016-08-17 13:02:13 -07:00
39577f86d1 Fix rfind (and other finders). Fixes bug https://svn.boost.org/trac/boost/ticket/9518 2016-08-14 11:20:28 -07:00
8392991c46 Remove extraneous semicolon; no functional change 2016-08-14 11:19:32 -07:00
c5b1256650 rename routines in detail namespace so that someone who includes both <string_ref> and <string_view> won't get duplicate decls 2016-08-14 11:11:12 -07:00
c56dd13592 Mark the copy ctor/assignment operator as '= default' when the compiler supports it. This makes these types trivially copy/move assignable/constructible. See https://svn.boost.org/trac/boost/ticket/11684 2016-07-27 11:18:18 -07:00
181f302ee4 Fix Ticket 12140; mark only single-arg ctor as explicit. Thanks to Thimo for the patch. 2016-06-15 15:50:21 -07:00
287844fe76 Merge branch 'develop' of github.com:boostorg/utility into develop 2016-06-15 14:52:40 -07:00
3982b6d633 Ensure the file ends with a newline. Fixes compiler warnings. 2016-04-14 19:20:15 +03:00
0b492bee9c Re-install string_ref - to be removed in the future 2016-04-14 07:50:28 -07:00
a9236d00a9 Ensure the file ends with a newline. Fixes compiler warnings. 2016-03-26 14:00:12 +03:00
4313bfc323 Revert "Remove the 'basic_string_ref template; use 'basic_string_view' instead. Keep the string_ref, etc typedefs around, though"
This reverts commit 8ab8e36dcf.
2016-03-07 08:45:25 -08:00
f61c94e812 Merge ADL protection for Boost.Operators from 'develop' 2016-03-05 11:32:26 +01:00
1dfacff7ec Renamed namespace detail to operators_detail 2016-02-23 20:30:16 +01:00
a25ac4550b Removed unused overloads 2016-02-22 20:46:58 +01:00
d767054a79 Merge branch 'develop' of github.com:boostorg/utility into develop 2016-02-22 20:39:26 +01:00
08a1b7da61 Added ADL protector 2016-02-22 20:39:16 +01:00
8ab8e36dcf Remove the 'basic_string_ref template; use 'basic_string_view' instead. Keep the string_ref, etc typedefs around, though 2016-02-17 11:32:16 -08:00
1caa745dd7 Introduce new 'string_view' to match the one in the standard. Step #2 (up next) is to retire string_ref in favor of string_view 2015-12-21 11:39:59 -08:00
cf5ad341ed Added a missing include. 2015-09-11 19:31:18 +03:00
1f6de83fe2 Merge pull request #20 from MarcelRaad/patch-1
Remove deprecated include
2015-09-11 19:06:38 +03:00
cb6500161b Remove deprecated include
All that boost/iterator.hpp does is pull std::iterator into namespace boost. A comment in that header mentions: "This header is obsolete and will be deprecated."
2015-09-11 17:49:23 +02:00
13610caa36 Update copyright notice; change to_string to avoid UB by calling a different constructor. Fixes #11150 2015-03-28 12:02:41 -07:00
6bcf4f92bf Merge pull request #19 from akumta/patch-1
Update string_ref_test2.cpp
2015-02-27 09:26:11 +03:00
fa8301a56a Update string_ref_test2.cpp
For ticket# 10838
2015-02-25 10:49:14 -08:00
7306c8c359 Merge branch 'develop' 2014-09-06 22:19:24 +04:00
492fd7f091 Moved enable_if to Boost.Core. 2014-08-18 18:57:40 +04:00
4fbd789253 Merge pull request #18 from danieljames/metadata
Create metadata file.
2014-08-18 18:49:04 +04:00
4522603132 Add metadata file. 2014-08-18 15:12:15 +01:00
2ec0488e2a Merge pull request #16 from danieljames/compressed-pair-redirect
Add a redirect for the compressed pair docs.
2014-07-04 21:56:14 +04:00
520dff9270 Add a redirect for the compressed pair docs. 2014-06-30 22:58:27 +01:00
8e24c798ad Merge pull request #15 from boostorg/next_prior_fix_iterator_backtracking
Reworked next() and prior() taking the distance arguments.
2014-06-25 22:26:44 +04:00
651a869d4f Reworked next() and prior() taking the distance arguments.
The new version should provide the expected behavior in the case (prior(v.end(), v.size()) == v.begin()). It should also work with integers now, as was originally intended by David Abrahams. Added tests to verify these new use cases.
2014-06-24 01:05:32 +04:00
41 changed files with 3560 additions and 355 deletions

400
.travis.yml Normal file
View File

@ -0,0 +1,400 @@
# Copyright 2016, 2017 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
language: cpp
sudo: false
python: "2.7"
os:
- linux
- osx
branches:
only:
- master
- develop
env:
matrix:
- BOGUS_JOB=true
matrix:
exclude:
- env: BOGUS_JOB=true
include:
- os: linux
env: TOOLSET=gcc COMPILER=g++ CXXSTD=c++03
- os: linux
env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=c++03
addons:
apt:
packages:
- g++-4.7
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-4.7 CXXSTD=c++11
addons:
apt:
packages:
- g++-4.7
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=c++03
addons:
apt:
packages:
- g++-4.8
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=c++11
addons:
apt:
packages:
- g++-4.8
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=c++03
addons:
apt:
packages:
- g++-4.9
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=c++11
addons:
apt:
packages:
- g++-4.9
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++03
addons:
apt:
packages:
- g++-5
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++11
addons:
apt:
packages:
- g++-5
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++14
addons:
apt:
packages:
- g++-5
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-5 CXXSTD=c++1z
addons:
apt:
packages:
- g++-5
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++03
addons:
apt:
packages:
- g++-6
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++11
addons:
apt:
packages:
- g++-6
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++14
addons:
apt:
packages:
- g++-6
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=gcc COMPILER=g++-6 CXXSTD=c++1z
addons:
apt:
packages:
- g++-6
sources:
- ubuntu-toolchain-r-test
- os: linux
dist: trusty
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++03
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
dist: trusty
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++11
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
dist: trusty
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++14
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
dist: trusty
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=c++1z
addons:
apt:
packages:
- g++-7
sources:
- ubuntu-toolchain-r-test
- os: linux
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++03
- os: linux
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++11
- os: linux
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=c++03
addons:
apt:
packages:
- clang-3.5
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.5
- os: linux
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=c++11
addons:
apt:
packages:
- clang-3.5
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.5
- os: linux
env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=c++03
addons:
apt:
packages:
- clang-3.6
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.6
- os: linux
env: TOOLSET=clang COMPILER=clang++-3.6 CXXSTD=c++11
addons:
apt:
packages:
- clang-3.6
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.6
- os: linux
env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=c++03
addons:
apt:
packages:
- clang-3.7
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7
- os: linux
env: TOOLSET=clang COMPILER=clang++-3.7 CXXSTD=c++11
addons:
apt:
packages:
- clang-3.7
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7
- os: linux
env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++03
addons:
apt:
packages:
- clang-3.8
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
- os: linux
env: TOOLSET=clang COMPILER=clang++-3.8 CXXSTD=c++11
addons:
apt:
packages:
- clang-3.8
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
- os: linux
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++03
addons:
apt:
packages:
- clang-3.9
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.9
- os: linux
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++11
addons:
apt:
packages:
- clang-3.9
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.9
- os: linux
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++14
addons:
apt:
packages:
- clang-3.9
- libstdc++-5-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.9
- os: linux
env: TOOLSET=clang COMPILER=clang++-3.9 CXXSTD=c++1z
addons:
apt:
packages:
- clang-3.9
- libstdc++-5-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.9
- os: linux
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++03
addons:
apt:
packages:
- clang-4.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- os: linux
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++11
addons:
apt:
packages:
- clang-4.0
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- os: linux
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++14
addons:
apt:
packages:
- clang-4.0
- libstdc++-6-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- os: linux
env: TOOLSET=clang COMPILER=clang++-4.0 CXXSTD=c++1z
addons:
apt:
packages:
- clang-4.0
- libstdc++-6-dev
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-4.0
- os: osx
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++03
- os: osx
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++11
- os: osx
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++14
- os: osx
env: TOOLSET=clang COMPILER=clang++ CXXSTD=c++1z
install:
- cd ..
- git clone -b $TRAVIS_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
- cd boost-root
- git submodule update --init tools/build
- git submodule update --init libs/config
- git submodule update --init tools/boostdep
- cp -r $TRAVIS_BUILD_DIR/* libs/utility
- python tools/boostdep/depinst/depinst.py utility
- ./bootstrap.sh
- ./b2 headers
script:
- |-
echo "using $TOOLSET : : $COMPILER : <cxxflags>-std=$CXXSTD ;" > ~/user-config.jam
- ./b2 libs/utility/test toolset=$TOOLSET
notifications:
email:
on_success: always

View File

@ -117,3 +117,11 @@ boostbook standalone_string_ref
# How far down we go with TOC's
<xsl:param>generate.section.toc.level=1
;
###############################################################################
alias boostdoc ;
explicit boostdoc ;
alias boostrelease :
standalone_base_from_member standalone_compressed_pair
standalone_declval standalone_string_ref ;
explicit boostrelease ;

View File

@ -1,8 +1,11 @@
// Boost next_prior.hpp header file ---------------------------------------//
// (C) Copyright Dave Abrahams and Daniel Walker 1999-2003. 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)
// (C) Copyright Dave Abrahams and Daniel Walker 1999-2003.
// Copyright (c) Andrey Semashev 2017
//
// 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/utility for documentation.
@ -13,6 +16,14 @@
#define BOOST_NEXT_PRIOR_HPP_INCLUDED
#include <iterator>
#include <boost/config.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/type_traits/has_plus.hpp>
#include <boost/type_traits/has_plus_assign.hpp>
#include <boost/type_traits/has_minus.hpp>
#include <boost/type_traits/has_minus_assign.hpp>
#include <boost/iterator/advance.hpp>
#include <boost/iterator/reverse_iterator.hpp>
namespace boost {
@ -26,14 +37,133 @@ namespace boost {
// Contributed by Dave Abrahams
namespace next_prior_detail {
// The trait attempts to detect if the T type is an iterator. Class-type iterators are assumed
// to have the nested type iterator_category. Strictly speaking, this is not required to be the
// case (e.g. a user can specialize iterator_traits for T without defining T::iterator_category).
// Still, this is a good heuristic in practice, and we can't do anything better anyway.
// Since C++17 we can test for iterator_traits<T>::iterator_category presence instead as it is
// required to be only present for iterators.
template< typename T, typename Void = void >
struct is_iterator
{
static BOOST_CONSTEXPR_OR_CONST bool value = false;
};
template< typename T >
struct is_iterator< T, typename enable_if_has_type< typename T::iterator_category >::type >
{
static BOOST_CONSTEXPR_OR_CONST bool value = true;
};
template< typename T >
struct is_iterator< T*, void >
{
static BOOST_CONSTEXPR_OR_CONST bool value = true;
};
template< typename T, typename Distance, bool HasPlus = has_plus< T, Distance >::value >
struct next_plus_impl;
template< typename T, typename Distance >
struct next_plus_impl< T, Distance, true >
{
static T call(T x, Distance n)
{
return x + n;
}
};
template< typename T, typename Distance, bool HasPlusAssign = has_plus_assign< T, Distance >::value >
struct next_plus_assign_impl :
public next_plus_impl< T, Distance >
{
};
template< typename T, typename Distance >
struct next_plus_assign_impl< T, Distance, true >
{
static T call(T x, Distance n)
{
x += n;
return x;
}
};
template< typename T, typename Distance, bool IsIterator = is_iterator< T >::value >
struct next_advance_impl :
public next_plus_assign_impl< T, Distance >
{
};
template< typename T, typename Distance >
struct next_advance_impl< T, Distance, true >
{
static T call(T x, Distance n)
{
boost::iterators::advance(x, n);
return x;
}
};
template< typename T, typename Distance, bool HasMinus = has_minus< T, Distance >::value >
struct prior_minus_impl;
template< typename T, typename Distance >
struct prior_minus_impl< T, Distance, true >
{
static T call(T x, Distance n)
{
return x - n;
}
};
template< typename T, typename Distance, bool HasMinusAssign = has_minus_assign< T, Distance >::value >
struct prior_minus_assign_impl :
public prior_minus_impl< T, Distance >
{
};
template< typename T, typename Distance >
struct prior_minus_assign_impl< T, Distance, true >
{
static T call(T x, Distance n)
{
x -= n;
return x;
}
};
template< typename T, typename Distance, bool IsIterator = is_iterator< T >::value >
struct prior_advance_impl :
public prior_minus_assign_impl< T, Distance >
{
};
template< typename T, typename Distance >
struct prior_advance_impl< T, Distance, true >
{
static T call(T x, Distance n)
{
// Avoid negating n to sidestep possible integer overflow
boost::iterators::reverse_iterator< T > rx(x);
boost::iterators::advance(rx, n);
return rx.base();
}
};
} // namespace next_prior_detail
template <class T>
inline T next(T x) { return ++x; }
template <class T, class Distance>
inline T next(T x, Distance n)
{
std::advance(x, n);
return x;
return next_prior_detail::next_advance_impl< T, Distance >::call(x, n);
}
template <class T>
@ -42,8 +172,7 @@ inline T prior(T x) { return --x; }
template <class T, class Distance>
inline T prior(T x, Distance n)
{
std::advance(x, -n);
return x;
return next_prior_detail::prior_advance_impl< T, Distance >::call(x, n);
}
} // namespace boost

View File

@ -1,6 +1,7 @@
// Boost operators.hpp header file ----------------------------------------//
// (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001.
// (C) Copyright Daniel Frey 2002-2016.
// 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)
@ -8,6 +9,8 @@
// See http://www.boost.org/libs/utility/operators.htm for documentation.
// Revision History
// 22 Feb 16 Added ADL protection, preserve old work-arounds in
// operators_v1.hpp and clean up this file. (Daniel Frey)
// 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++
// (Matthew Bradbury, fixes #4432)
// 07 Aug 08 Added "euclidean" spelling. (Daniel Frey)
@ -24,8 +27,8 @@
// additional classes for groups of related operators added;
// workaround for empty base class optimization
// bug of GCC 3.0 (Helmut Zeisel)
// 25 Jun 01 output_iterator_helper changes: removed default template
// parameters, added support for self-proxying, additional
// 25 Jun 01 output_iterator_helper changes: removed default template
// parameters, added support for self-proxying, additional
// documentation and tests (Aleksey Gurtovoy)
// 29 May 01 Added operator classes for << and >>. Added input and output
// iterator helper classes. Added classes to connect equality and
@ -38,18 +41,18 @@
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
// refactoring of compiler workarounds, additional documentation
// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
// Dave Abrahams)
// Dave Abrahams)
// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and
// Jeremy Siek (Dave Abrahams)
// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5
// (Mark Rodgers)
// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy)
// 10 Jun 00 Support for the base class chaining technique was added
// (Aleksey Gurtovoy). See documentation and the comments below
// for the details.
// (Aleksey Gurtovoy). See documentation and the comments below
// for the details.
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary
// specializations of dividable, subtractable, modable (Ed Brey)
// specializations of dividable, subtractable, modable (Ed Brey)
// 17 Nov 99 Add comments (Beman Dawes)
// Remove unnecessary specialization of operators<> (Ed Brey)
// 15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two
@ -60,8 +63,8 @@
// 10 Nov 99 Initial version
// 10 Jun 00:
// An additional optional template parameter was added to most of
// operator templates to support the base class chaining technique (see
// An additional optional template parameter was added to most of
// operator templates to support the base class chaining technique (see
// documentation for the details). Unfortunately, a straightforward
// implementation of this change would have broken compatibility with the
// previous version of the library by making it impossible to use the same
@ -70,20 +73,28 @@
// issue at the cost of some simplicity.
//
// One of the complications is an existence of special auxiliary class template
// 'is_chained_base<>' (see 'detail' namespace below), which is used
// 'is_chained_base<>' (see 'operators_detail' namespace below), which is used
// to determine whether its template parameter is a library's operator template
// or not. You have to specialize 'is_chained_base<>' for each new
// or not. You have to specialize 'is_chained_base<>' for each new
// operator template you add to the library.
//
// However, most of the non-trivial implementation details are hidden behind
// However, most of the non-trivial implementation details are hidden behind
// several local macros defined below, and as soon as you understand them,
// you understand the whole library implementation.
// you understand the whole library implementation.
#ifndef BOOST_OPERATORS_HPP
#define BOOST_OPERATORS_HPP
// If old work-arounds are needed, refer to the preserved version without
// ADL protection.
#if defined(BOOST_NO_OPERATORS_IN_NAMESPACE) || defined(BOOST_USE_OPERATORS_V1)
#include "operators_v1.hpp"
#else
#include <cstddef>
#include <iterator>
#include <boost/config.hpp>
#include <boost/iterator.hpp>
#include <boost/detail/workaround.hpp>
#if defined(__sgi) && !defined(__GNUC__)
@ -91,35 +102,30 @@
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, < 1600)
# pragma warning( disable : 4284 ) // complaint about return type of
# pragma warning( disable : 4284 ) // complaint about return type of
#endif // operator-> not begin a UDT
namespace boost {
namespace detail {
template <typename T> class empty_base {};
} // namespace detail
} // namespace boost
// In this section we supply the xxxx1 and xxxx2 forms of the operator
// templates, which are explicitly targeted at the 1-type-argument and
// 2-type-argument operator forms, respectively. Some compilers get confused
// when inline friend functions are overloaded in namespaces other than the
// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of
// these templates must go in the global namespace.
// 2-type-argument operator forms, respectively.
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
namespace boost
{
#endif
namespace operators_impl
{
namespace operators_detail
{
template <typename T> class empty_base {};
} // namespace operators_detail
// Basic operator classes (contributed by Dave Abrahams) ------------------//
// Note that friend functions defined in a class are implicitly inline.
// See the C++ std, 11.4 [class.friend] paragraph 5
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct less_than_comparable2 : B
{
friend bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); }
@ -130,7 +136,7 @@ struct less_than_comparable2 : B
friend bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); }
};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct less_than_comparable1 : B
{
friend bool operator>(const T& x, const T& y) { return y < x; }
@ -138,7 +144,7 @@ struct less_than_comparable1 : B
friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct equality_comparable2 : B
{
friend bool operator==(const U& y, const T& x) { return x == y; }
@ -146,7 +152,7 @@ struct equality_comparable2 : B
friend bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); }
};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct equality_comparable1 : B
{
friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
@ -164,39 +170,39 @@ struct equality_comparable1 : B
// If the compiler has no NRVO, this is the best symmetric
// implementation available.
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
friend T operator OP( const U& lhs, const T& rhs ) \
{ T nrv( rhs ); nrv OP##= lhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = operators_detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
friend T operator OP( const U& lhs, const T& rhs ) \
{ T nrv( rhs ); nrv OP##= lhs; return nrv; } \
}; \
\
template <class T, class B = operators_detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
};
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
template <class T, class U, class B = operators_detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
template <class T, class U, class B = operators_detail::empty_base<T> > \
struct BOOST_OPERATOR2_LEFT(NAME) : B \
{ \
friend T operator OP( const U& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
template <class T, class B = operators_detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
@ -211,34 +217,34 @@ struct NAME##1 : B \
// optimization opportunities to the compiler :)
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
template <class T, class U, class B = operators_detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
template <class T, class B = operators_detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
};
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
template <class T, class U, class B = operators_detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
}; \
\
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
template <class T, class U, class B = operators_detail::empty_base<T> > \
struct BOOST_OPERATOR2_LEFT(NAME) : B \
{ \
friend T operator OP( const U& lhs, const T& rhs ) \
{ return T( lhs ) OP##= rhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
template <class T, class B = operators_detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
@ -261,7 +267,7 @@ BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
// incrementable and decrementable contributed by Jeremy Siek
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct incrementable : B
{
friend T operator++(T& x, int)
@ -274,7 +280,7 @@ private: // The use of this typedef works around a Borland bug
typedef T incrementable_type;
};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct decrementable : B
{
friend T operator--(T& x, int)
@ -289,16 +295,16 @@ private: // The use of this typedef works around a Borland bug
// Iterator operator classes (contributed by Jeremy Siek) ------------------//
template <class T, class P, class B = ::boost::detail::empty_base<T> >
template <class T, class P, class B = operators_detail::empty_base<T> >
struct dereferenceable : B
{
P operator->() const
{
return &*static_cast<const T&>(*this);
{
return &*static_cast<const T&>(*this);
}
};
template <class T, class I, class R, class B = ::boost::detail::empty_base<T> >
template <class T, class I, class R, class B = operators_detail::empty_base<T> >
struct indexable : B
{
R operator[](I n) const
@ -312,34 +318,34 @@ struct indexable : B
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
template <class T, class U, class B = operators_detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class B = operators_detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
};
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
template <class T, class U, class B = operators_detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
}; \
\
template <class T, class B = operators_detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
};
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
@ -349,7 +355,7 @@ BOOST_BINARY_OPERATOR( right_shiftable, >> )
#undef BOOST_BINARY_OPERATOR
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct equivalent2 : B
{
friend bool operator==(const T& x, const U& y)
@ -358,7 +364,7 @@ struct equivalent2 : B
}
};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct equivalent1 : B
{
friend bool operator==(const T&x, const T&y)
@ -367,7 +373,7 @@ struct equivalent1 : B
}
};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct partially_ordered2 : B
{
friend bool operator<=(const T& x, const U& y)
@ -384,7 +390,7 @@ struct partially_ordered2 : B
{ return static_cast<bool>(y < x) || static_cast<bool>(y == x); }
};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct partially_ordered1 : B
{
friend bool operator>(const T& x, const T& y)
@ -397,161 +403,161 @@ struct partially_ordered1 : B
// Combined operator classes (contributed by Daryle Walker) ----------------//
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct totally_ordered2
: less_than_comparable2<T, U
, equality_comparable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct totally_ordered1
: less_than_comparable1<T
, equality_comparable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct additive2
: addable2<T, U
, subtractable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct additive1
: addable1<T
, subtractable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct multiplicative2
: multipliable2<T, U
, dividable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct multiplicative1
: multipliable1<T
, dividable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct integer_multiplicative2
: multiplicative2<T, U
, modable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct integer_multiplicative1
: multiplicative1<T
, modable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct arithmetic2
: additive2<T, U
, multiplicative2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct arithmetic1
: additive1<T
, multiplicative1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct integer_arithmetic2
: additive2<T, U
, integer_multiplicative2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct integer_arithmetic1
: additive1<T
, integer_multiplicative1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct bitwise2
: xorable2<T, U
, andable2<T, U
, orable2<T, U, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct bitwise1
: xorable1<T
, andable1<T
, orable1<T, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct unit_steppable
: incrementable<T
, decrementable<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct shiftable2
: left_shiftable2<T, U
, right_shiftable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct shiftable1
: left_shiftable1<T
, right_shiftable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct ring_operators2
: additive2<T, U
, subtractable2_left<T, U
, multipliable2<T, U, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct ring_operators1
: additive1<T
, multipliable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct ordered_ring_operators2
: ring_operators2<T, U
, totally_ordered2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct ordered_ring_operators1
: ring_operators1<T
, totally_ordered1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct field_operators2
: ring_operators2<T, U
, dividable2<T, U
, dividable2_left<T, U, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct field_operators1
: ring_operators1<T
, dividable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct ordered_field_operators2
: field_operators2<T, U
, totally_ordered2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct ordered_field_operators1
: field_operators1<T
, totally_ordered1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct euclidian_ring_operators2
: ring_operators2<T, U
, dividable2<T, U
@ -560,26 +566,26 @@ struct euclidian_ring_operators2
, modable2_left<T, U, B
> > > > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct euclidian_ring_operators1
: ring_operators1<T
, dividable1<T
, modable1<T, B
> > > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct ordered_euclidian_ring_operators2
: totally_ordered2<T, U
, euclidian_ring_operators2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct ordered_euclidian_ring_operators1
: totally_ordered1<T
, euclidian_ring_operators1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct euclidean_ring_operators2
: ring_operators2<T, U
, dividable2<T, U
@ -588,43 +594,43 @@ struct euclidean_ring_operators2
, modable2_left<T, U, B
> > > > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct euclidean_ring_operators1
: ring_operators1<T
, dividable1<T
, modable1<T, B
> > > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = operators_detail::empty_base<T> >
struct ordered_euclidean_ring_operators2
: totally_ordered2<T, U
, euclidean_ring_operators2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct ordered_euclidean_ring_operators1
: totally_ordered1<T
, euclidean_ring_operators1<T, B
> > {};
template <class T, class P, class B = ::boost::detail::empty_base<T> >
template <class T, class P, class B = operators_detail::empty_base<T> >
struct input_iteratable
: equality_comparable1<T
, incrementable<T
, dereferenceable<T, P, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = operators_detail::empty_base<T> >
struct output_iteratable
: incrementable<T, B
> {};
template <class T, class P, class B = ::boost::detail::empty_base<T> >
template <class T, class P, class B = operators_detail::empty_base<T> >
struct forward_iteratable
: input_iteratable<T, P, B
> {};
template <class T, class P, class B = ::boost::detail::empty_base<T> >
template <class T, class P, class B = operators_detail::empty_base<T> >
struct bidirectional_iteratable
: forward_iteratable<T, P
, decrementable<T, B
@ -634,7 +640,7 @@ struct bidirectional_iteratable
// which is an indirect base class of bidirectional_iterable,
// random_access_iteratable must not be derived from totally_ordered1
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base<T> >
template <class T, class P, class D, class R, class B = operators_detail::empty_base<T> >
struct random_access_iteratable
: bidirectional_iteratable<T, P
, less_than_comparable1<T
@ -642,124 +648,64 @@ struct random_access_iteratable
, indexable<T, D, R, B
> > > > {};
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
} // namespace boost
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 -
//
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for
// two-argument forms. Note that these macros expect to be invoked from within
// boost.
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
// The template is already in boost so we have nothing to do.
# define BOOST_IMPORT_TEMPLATE4(template_name)
# define BOOST_IMPORT_TEMPLATE3(template_name)
# define BOOST_IMPORT_TEMPLATE2(template_name)
# define BOOST_IMPORT_TEMPLATE1(template_name)
#else // BOOST_NO_OPERATORS_IN_NAMESPACE
# ifndef BOOST_NO_USING_TEMPLATE
// Bring the names in with a using-declaration
// to avoid stressing the compiler.
# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
# else
// Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
// from working, we are forced to use inheritance for that compiler.
# define BOOST_IMPORT_TEMPLATE4(template_name) \
template <class T, class U, class V, class W, class B = ::boost::detail::empty_base<T> > \
struct template_name : ::template_name<T, U, V, W, B> {};
# define BOOST_IMPORT_TEMPLATE3(template_name) \
template <class T, class U, class V, class B = ::boost::detail::empty_base<T> > \
struct template_name : ::template_name<T, U, V, B> {};
# define BOOST_IMPORT_TEMPLATE2(template_name) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct template_name : ::template_name<T, U, B> {};
# define BOOST_IMPORT_TEMPLATE1(template_name) \
template <class T, class B = ::boost::detail::empty_base<T> > \
struct template_name : ::template_name<T, B> {};
# endif // BOOST_NO_USING_TEMPLATE
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
//
// Here's where we put it all together, defining the xxxx forms of the templates
// in namespace boost. We also define specializations of is_chained_base<> for
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
// necessary.
// Here's where we put it all together, defining the xxxx forms of the templates.
// We also define specializations of is_chained_base<> for
// the xxxx, xxxx1, and xxxx2 templates.
//
namespace operators_detail
{
// A type parameter is used instead of a plain bool because Borland's compiler
// didn't cope well with the more obvious non-type template parameter.
struct true_t {};
struct false_t {};
} // namespace operators_detail
// is_chained_base<> - a traits class used to distinguish whether an operator
// template argument is being used for base class chaining, or is specifying a
// 2nd argument type.
namespace boost {
// A type parameter is used instead of a plain bool because Borland's compiler
// didn't cope well with the more obvious non-type template parameter.
namespace detail {
struct true_t {};
struct false_t {};
} // namespace detail
// Unspecialized version assumes that most types are not being used for base
// class chaining. We specialize for the operator templates defined in this
// library.
template<class T> struct is_chained_base {
typedef ::boost::detail::false_t value;
typedef operators_detail::false_t value;
};
} // namespace boost
// Import a 4-type-argument operator template into boost (if necessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
BOOST_IMPORT_TEMPLATE4(template_name4) \
template<class T, class U, class V, class W, class B> \
struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > { \
typedef ::boost::detail::true_t value; \
// Provide a specialization of 'is_chained_base<>'
// for a 4-type-argument operator template.
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
template<class T, class U, class V, class W, class B> \
struct is_chained_base< template_name4<T, U, V, W, B> > { \
typedef operators_detail::true_t value; \
};
// Import a 3-type-argument operator template into boost (if necessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
BOOST_IMPORT_TEMPLATE3(template_name3) \
template<class T, class U, class V, class B> \
struct is_chained_base< ::boost::template_name3<T, U, V, B> > { \
typedef ::boost::detail::true_t value; \
// Provide a specialization of 'is_chained_base<>'
// for a 3-type-argument operator template.
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
template<class T, class U, class V, class B> \
struct is_chained_base< template_name3<T, U, V, B> > { \
typedef operators_detail::true_t value; \
};
// Import a 2-type-argument operator template into boost (if necessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
BOOST_IMPORT_TEMPLATE2(template_name2) \
template<class T, class U, class B> \
struct is_chained_base< ::boost::template_name2<T, U, B> > { \
typedef ::boost::detail::true_t value; \
// Provide a specialization of 'is_chained_base<>'
// for a 2-type-argument operator template.
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
template<class T, class U, class B> \
struct is_chained_base< template_name2<T, U, B> > { \
typedef operators_detail::true_t value; \
};
// Import a 1-type-argument operator template into boost (if necessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
BOOST_IMPORT_TEMPLATE1(template_name1) \
template<class T, class B> \
struct is_chained_base< ::boost::template_name1<T, B> > { \
typedef ::boost::detail::true_t value; \
// Provide a specialization of 'is_chained_base<>'
// for a 1-type-argument operator template.
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
template<class T, class B> \
struct is_chained_base< template_name1<T, B> > { \
typedef operators_detail::true_t value; \
};
// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
@ -776,34 +722,34 @@ template<class T> struct is_chained_base {
// implementation in terms of either '<template_name>1' or '<template_name>2'.
//
# define BOOST_OPERATOR_TEMPLATE(template_name) \
template <class T \
,class U = T \
,class B = ::boost::detail::empty_base<T> \
,class O = typename is_chained_base<U>::value \
> \
struct template_name : template_name##2<T, U, B> {}; \
\
template<class T, class U, class B> \
struct template_name<T, U, B, ::boost::detail::true_t> \
: template_name##1<T, U> {}; \
\
template <class T, class B> \
struct template_name<T, T, B, ::boost::detail::false_t> \
: template_name##1<T, B> {}; \
\
template<class T, class U, class B, class O> \
struct is_chained_base< ::boost::template_name<T, U, B, O> > { \
typedef ::boost::detail::true_t value; \
}; \
\
BOOST_OPERATOR_TEMPLATE2(template_name##2) \
# define BOOST_OPERATOR_TEMPLATE(template_name) \
template <class T \
,class U = T \
,class B = operators_detail::empty_base<T> \
,class O = typename is_chained_base<U>::value \
> \
struct template_name; \
\
template<class T, class U, class B> \
struct template_name<T, U, B, operators_detail::false_t> \
: template_name##2<T, U, B> {}; \
\
template<class T, class U> \
struct template_name<T, U, operators_detail::empty_base<T>, operators_detail::true_t> \
: template_name##1<T, U> {}; \
\
template <class T, class B> \
struct template_name<T, T, B, operators_detail::false_t> \
: template_name##1<T, B> {}; \
\
template<class T, class U, class B, class O> \
struct is_chained_base< template_name<T, U, B, O> > { \
typedef operators_detail::true_t value; \
}; \
\
BOOST_OPERATOR_TEMPLATE2(template_name##2) \
BOOST_OPERATOR_TEMPLATE1(template_name##1)
namespace boost {
BOOST_OPERATOR_TEMPLATE(less_than_comparable)
BOOST_OPERATOR_TEMPLATE(equality_comparable)
BOOST_OPERATOR_TEMPLATE(multipliable)
@ -857,13 +803,7 @@ BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
#undef BOOST_OPERATOR_TEMPLATE3
#undef BOOST_OPERATOR_TEMPLATE2
#undef BOOST_OPERATOR_TEMPLATE1
#undef BOOST_IMPORT_TEMPLATE1
#undef BOOST_IMPORT_TEMPLATE2
#undef BOOST_IMPORT_TEMPLATE3
#undef BOOST_IMPORT_TEMPLATE4
// The following 'operators' classes can only be used portably if the derived class
// declares ALL of the required member operators.
template <class T, class U>
struct operators2
: totally_ordered2<T,U
@ -891,13 +831,13 @@ template <class T,
class R = V const &>
struct input_iterator_helper
: input_iteratable<T, P
, boost::iterator<std::input_iterator_tag, V, D, P, R
, std::iterator<std::input_iterator_tag, V, D, P, R
> > {};
template<class T>
struct output_iterator_helper
: output_iteratable<T
, boost::iterator<std::output_iterator_tag, void, void, void, void
, std::iterator<std::output_iterator_tag, void, void, void, void
> >
{
T& operator*() { return static_cast<T&>(*this); }
@ -911,7 +851,7 @@ template <class T,
class R = V&>
struct forward_iterator_helper
: forward_iteratable<T, P
, boost::iterator<std::forward_iterator_tag, V, D, P, R
, std::iterator<std::forward_iterator_tag, V, D, P, R
> > {};
template <class T,
@ -921,17 +861,17 @@ template <class T,
class R = V&>
struct bidirectional_iterator_helper
: bidirectional_iteratable<T, P
, boost::iterator<std::bidirectional_iterator_tag, V, D, P, R
, std::iterator<std::bidirectional_iterator_tag, V, D, P, R
> > {};
template <class T,
class V,
class V,
class D = std::ptrdiff_t,
class P = V*,
class R = V&>
struct random_access_iterator_helper
: random_access_iteratable<T, P, D, R
, boost::iterator<std::random_access_iterator_tag, V, D, P, R
, std::iterator<std::random_access_iterator_tag, V, D, P, R
> >
{
friend D requires_difference_operator(const T& x, const T& y) {
@ -939,10 +879,14 @@ struct random_access_iterator_helper
}
}; // random_access_iterator_helper
} // namespace operators_impl
using namespace operators_impl;
} // namespace boost
#if defined(__sgi) && !defined(__GNUC__)
#pragma reset woff 1234
#endif
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
#endif // BOOST_OPERATORS_HPP

View File

@ -0,0 +1,951 @@
// Boost operators.hpp header file ----------------------------------------//
// (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001.
// 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/utility/operators.htm for documentation.
// Revision History
// 22 Feb 16 Preserve old work-arounds. (Daniel Frey)
// 16 Dec 10 Limit warning suppression for 4284 to older versions of VC++
// (Matthew Bradbury, fixes #4432)
// 07 Aug 08 Added "euclidean" spelling. (Daniel Frey)
// 03 Apr 08 Make sure "convertible to bool" is sufficient
// for T::operator<, etc. (Daniel Frey)
// 24 May 07 Changed empty_base to depend on T, see
// http://svn.boost.org/trac/boost/ticket/979
// 21 Oct 02 Modified implementation of operators to allow compilers with a
// correct named return value optimization (NRVO) to produce optimal
// code. (Daniel Frey)
// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
// 27 Aug 01 'left' form for non commutative operators added;
// additional classes for groups of related operators added;
// workaround for empty base class optimization
// bug of GCC 3.0 (Helmut Zeisel)
// 25 Jun 01 output_iterator_helper changes: removed default template
// parameters, added support for self-proxying, additional
// documentation and tests (Aleksey Gurtovoy)
// 29 May 01 Added operator classes for << and >>. Added input and output
// iterator helper classes. Added classes to connect equality and
// relational operators. Added classes for groups of related
// operators. Reimplemented example operator and iterator helper
// classes in terms of the new groups. (Daryle Walker, with help
// from Alexy Gurtovoy)
// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
// supplied arguments from actually being used (Dave Abrahams)
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
// refactoring of compiler workarounds, additional documentation
// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
// Dave Abrahams)
// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and
// Jeremy Siek (Dave Abrahams)
// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5
// (Mark Rodgers)
// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy)
// 10 Jun 00 Support for the base class chaining technique was added
// (Aleksey Gurtovoy). See documentation and the comments below
// for the details.
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary
// specializations of dividable, subtractable, modable (Ed Brey)
// 17 Nov 99 Add comments (Beman Dawes)
// Remove unnecessary specialization of operators<> (Ed Brey)
// 15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two
// operators.(Beman Dawes)
// 12 Nov 99 Add operators templates (Ed Brey)
// 11 Nov 99 Add single template parameter version for compilers without
// partial specialization (Beman Dawes)
// 10 Nov 99 Initial version
// 10 Jun 00:
// An additional optional template parameter was added to most of
// operator templates to support the base class chaining technique (see
// documentation for the details). Unfortunately, a straightforward
// implementation of this change would have broken compatibility with the
// previous version of the library by making it impossible to use the same
// template name (e.g. 'addable') for both the 1- and 2-argument versions of
// an operator template. This implementation solves the backward-compatibility
// issue at the cost of some simplicity.
//
// One of the complications is an existence of special auxiliary class template
// 'is_chained_base<>' (see 'detail' namespace below), which is used
// to determine whether its template parameter is a library's operator template
// or not. You have to specialize 'is_chained_base<>' for each new
// operator template you add to the library.
//
// However, most of the non-trivial implementation details are hidden behind
// several local macros defined below, and as soon as you understand them,
// you understand the whole library implementation.
#ifndef BOOST_OPERATORS_V1_HPP
#define BOOST_OPERATORS_V1_HPP
#include <cstddef>
#include <iterator>
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#if defined(__sgi) && !defined(__GNUC__)
# pragma set woff 1234
#endif
#if BOOST_WORKAROUND(BOOST_MSVC, < 1600)
# pragma warning( disable : 4284 ) // complaint about return type of
#endif // operator-> not begin a UDT
namespace boost {
namespace detail {
template <typename T> class empty_base {};
} // namespace detail
} // namespace boost
// In this section we supply the xxxx1 and xxxx2 forms of the operator
// templates, which are explicitly targeted at the 1-type-argument and
// 2-type-argument operator forms, respectively. Some compilers get confused
// when inline friend functions are overloaded in namespaces other than the
// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of
// these templates must go in the global namespace.
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
namespace boost
{
#endif
// Basic operator classes (contributed by Dave Abrahams) ------------------//
// Note that friend functions defined in a class are implicitly inline.
// See the C++ std, 11.4 [class.friend] paragraph 5
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct less_than_comparable2 : B
{
friend bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); }
friend bool operator>=(const T& x, const U& y) { return !static_cast<bool>(x < y); }
friend bool operator>(const U& x, const T& y) { return y < x; }
friend bool operator<(const U& x, const T& y) { return y > x; }
friend bool operator<=(const U& x, const T& y) { return !static_cast<bool>(y < x); }
friend bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); }
};
template <class T, class B = ::boost::detail::empty_base<T> >
struct less_than_comparable1 : B
{
friend bool operator>(const T& x, const T& y) { return y < x; }
friend bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); }
friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct equality_comparable2 : B
{
friend bool operator==(const U& y, const T& x) { return x == y; }
friend bool operator!=(const U& y, const T& x) { return !static_cast<bool>(x == y); }
friend bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); }
};
template <class T, class B = ::boost::detail::empty_base<T> >
struct equality_comparable1 : B
{
friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
};
// A macro which produces "name_2left" from "name".
#define BOOST_OPERATOR2_LEFT(name) name##2##_##left
// NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
// This is the optimal implementation for ISO/ANSI C++,
// but it requires the compiler to implement the NRVO.
// If the compiler has no NRVO, this is the best symmetric
// implementation available.
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
friend T operator OP( const U& lhs, const T& rhs ) \
{ T nrv( rhs ); nrv OP##= lhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
};
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct BOOST_OPERATOR2_LEFT(NAME) : B \
{ \
friend T operator OP( const U& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
};
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
// For compilers without NRVO the following code is optimal, but not
// symmetric! Note that the implementation of
// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
// optimization opportunities to the compiler :)
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
};
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
}; \
\
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct BOOST_OPERATOR2_LEFT(NAME) : B \
{ \
friend T operator OP( const U& lhs, const T& rhs ) \
{ return T( lhs ) OP##= rhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
};
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
#undef BOOST_OPERATOR2_LEFT
// incrementable and decrementable contributed by Jeremy Siek
template <class T, class B = ::boost::detail::empty_base<T> >
struct incrementable : B
{
friend T operator++(T& x, int)
{
incrementable_type nrv(x);
++x;
return nrv;
}
private: // The use of this typedef works around a Borland bug
typedef T incrementable_type;
};
template <class T, class B = ::boost::detail::empty_base<T> >
struct decrementable : B
{
friend T operator--(T& x, int)
{
decrementable_type nrv(x);
--x;
return nrv;
}
private: // The use of this typedef works around a Borland bug
typedef T decrementable_type;
};
// Iterator operator classes (contributed by Jeremy Siek) ------------------//
template <class T, class P, class B = ::boost::detail::empty_base<T> >
struct dereferenceable : B
{
P operator->() const
{
return &*static_cast<const T&>(*this);
}
};
template <class T, class I, class R, class B = ::boost::detail::empty_base<T> >
struct indexable : B
{
R operator[](I n) const
{
return *(static_cast<const T&>(*this) + n);
}
};
// More operator classes (contributed by Daryle Walker) --------------------//
// (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
};
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
};
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
BOOST_BINARY_OPERATOR( left_shiftable, << )
BOOST_BINARY_OPERATOR( right_shiftable, >> )
#undef BOOST_BINARY_OPERATOR
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct equivalent2 : B
{
friend bool operator==(const T& x, const U& y)
{
return !static_cast<bool>(x < y) && !static_cast<bool>(x > y);
}
};
template <class T, class B = ::boost::detail::empty_base<T> >
struct equivalent1 : B
{
friend bool operator==(const T&x, const T&y)
{
return !static_cast<bool>(x < y) && !static_cast<bool>(y < x);
}
};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct partially_ordered2 : B
{
friend bool operator<=(const T& x, const U& y)
{ return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
friend bool operator>=(const T& x, const U& y)
{ return static_cast<bool>(x > y) || static_cast<bool>(x == y); }
friend bool operator>(const U& x, const T& y)
{ return y < x; }
friend bool operator<(const U& x, const T& y)
{ return y > x; }
friend bool operator<=(const U& x, const T& y)
{ return static_cast<bool>(y > x) || static_cast<bool>(y == x); }
friend bool operator>=(const U& x, const T& y)
{ return static_cast<bool>(y < x) || static_cast<bool>(y == x); }
};
template <class T, class B = ::boost::detail::empty_base<T> >
struct partially_ordered1 : B
{
friend bool operator>(const T& x, const T& y)
{ return y < x; }
friend bool operator<=(const T& x, const T& y)
{ return static_cast<bool>(x < y) || static_cast<bool>(x == y); }
friend bool operator>=(const T& x, const T& y)
{ return static_cast<bool>(y < x) || static_cast<bool>(x == y); }
};
// Combined operator classes (contributed by Daryle Walker) ----------------//
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct totally_ordered2
: less_than_comparable2<T, U
, equality_comparable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct totally_ordered1
: less_than_comparable1<T
, equality_comparable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct additive2
: addable2<T, U
, subtractable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct additive1
: addable1<T
, subtractable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct multiplicative2
: multipliable2<T, U
, dividable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct multiplicative1
: multipliable1<T
, dividable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct integer_multiplicative2
: multiplicative2<T, U
, modable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct integer_multiplicative1
: multiplicative1<T
, modable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct arithmetic2
: additive2<T, U
, multiplicative2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct arithmetic1
: additive1<T
, multiplicative1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct integer_arithmetic2
: additive2<T, U
, integer_multiplicative2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct integer_arithmetic1
: additive1<T
, integer_multiplicative1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct bitwise2
: xorable2<T, U
, andable2<T, U
, orable2<T, U, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct bitwise1
: xorable1<T
, andable1<T
, orable1<T, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct unit_steppable
: incrementable<T
, decrementable<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct shiftable2
: left_shiftable2<T, U
, right_shiftable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct shiftable1
: left_shiftable1<T
, right_shiftable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct ring_operators2
: additive2<T, U
, subtractable2_left<T, U
, multipliable2<T, U, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct ring_operators1
: additive1<T
, multipliable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct ordered_ring_operators2
: ring_operators2<T, U
, totally_ordered2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct ordered_ring_operators1
: ring_operators1<T
, totally_ordered1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct field_operators2
: ring_operators2<T, U
, dividable2<T, U
, dividable2_left<T, U, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct field_operators1
: ring_operators1<T
, dividable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct ordered_field_operators2
: field_operators2<T, U
, totally_ordered2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct ordered_field_operators1
: field_operators1<T
, totally_ordered1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct euclidian_ring_operators2
: ring_operators2<T, U
, dividable2<T, U
, dividable2_left<T, U
, modable2<T, U
, modable2_left<T, U, B
> > > > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct euclidian_ring_operators1
: ring_operators1<T
, dividable1<T
, modable1<T, B
> > > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct ordered_euclidian_ring_operators2
: totally_ordered2<T, U
, euclidian_ring_operators2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct ordered_euclidian_ring_operators1
: totally_ordered1<T
, euclidian_ring_operators1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct euclidean_ring_operators2
: ring_operators2<T, U
, dividable2<T, U
, dividable2_left<T, U
, modable2<T, U
, modable2_left<T, U, B
> > > > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct euclidean_ring_operators1
: ring_operators1<T
, dividable1<T
, modable1<T, B
> > > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct ordered_euclidean_ring_operators2
: totally_ordered2<T, U
, euclidean_ring_operators2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct ordered_euclidean_ring_operators1
: totally_ordered1<T
, euclidean_ring_operators1<T, B
> > {};
template <class T, class P, class B = ::boost::detail::empty_base<T> >
struct input_iteratable
: equality_comparable1<T
, incrementable<T
, dereferenceable<T, P, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
struct output_iteratable
: incrementable<T, B
> {};
template <class T, class P, class B = ::boost::detail::empty_base<T> >
struct forward_iteratable
: input_iteratable<T, P, B
> {};
template <class T, class P, class B = ::boost::detail::empty_base<T> >
struct bidirectional_iteratable
: forward_iteratable<T, P
, decrementable<T, B
> > {};
// To avoid repeated derivation from equality_comparable,
// which is an indirect base class of bidirectional_iterable,
// random_access_iteratable must not be derived from totally_ordered1
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base<T> >
struct random_access_iteratable
: bidirectional_iteratable<T, P
, less_than_comparable1<T
, additive2<T, D
, indexable<T, D, R, B
> > > > {};
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
} // namespace boost
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 -
//
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for
// two-argument forms. Note that these macros expect to be invoked from within
// boost.
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
// The template is already in boost so we have nothing to do.
# define BOOST_IMPORT_TEMPLATE4(template_name)
# define BOOST_IMPORT_TEMPLATE3(template_name)
# define BOOST_IMPORT_TEMPLATE2(template_name)
# define BOOST_IMPORT_TEMPLATE1(template_name)
#else // BOOST_NO_OPERATORS_IN_NAMESPACE
# ifndef BOOST_NO_USING_TEMPLATE
// Bring the names in with a using-declaration
// to avoid stressing the compiler.
# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
# else
// Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
// from working, we are forced to use inheritance for that compiler.
# define BOOST_IMPORT_TEMPLATE4(template_name) \
template <class T, class U, class V, class W, class B = ::boost::detail::empty_base<T> > \
struct template_name : ::template_name<T, U, V, W, B> {};
# define BOOST_IMPORT_TEMPLATE3(template_name) \
template <class T, class U, class V, class B = ::boost::detail::empty_base<T> > \
struct template_name : ::template_name<T, U, V, B> {};
# define BOOST_IMPORT_TEMPLATE2(template_name) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct template_name : ::template_name<T, U, B> {};
# define BOOST_IMPORT_TEMPLATE1(template_name) \
template <class T, class B = ::boost::detail::empty_base<T> > \
struct template_name : ::template_name<T, B> {};
# endif // BOOST_NO_USING_TEMPLATE
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
//
// Here's where we put it all together, defining the xxxx forms of the templates
// in namespace boost. We also define specializations of is_chained_base<> for
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
// necessary.
//
// is_chained_base<> - a traits class used to distinguish whether an operator
// template argument is being used for base class chaining, or is specifying a
// 2nd argument type.
namespace boost {
// A type parameter is used instead of a plain bool because Borland's compiler
// didn't cope well with the more obvious non-type template parameter.
namespace detail {
struct true_t {};
struct false_t {};
} // namespace detail
// Unspecialized version assumes that most types are not being used for base
// class chaining. We specialize for the operator templates defined in this
// library.
template<class T> struct is_chained_base {
typedef ::boost::detail::false_t value;
};
} // namespace boost
// Import a 4-type-argument operator template into boost (if necessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
BOOST_IMPORT_TEMPLATE4(template_name4) \
template<class T, class U, class V, class W, class B> \
struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > { \
typedef ::boost::detail::true_t value; \
};
// Import a 3-type-argument operator template into boost (if necessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
BOOST_IMPORT_TEMPLATE3(template_name3) \
template<class T, class U, class V, class B> \
struct is_chained_base< ::boost::template_name3<T, U, V, B> > { \
typedef ::boost::detail::true_t value; \
};
// Import a 2-type-argument operator template into boost (if necessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
BOOST_IMPORT_TEMPLATE2(template_name2) \
template<class T, class U, class B> \
struct is_chained_base< ::boost::template_name2<T, U, B> > { \
typedef ::boost::detail::true_t value; \
};
// Import a 1-type-argument operator template into boost (if necessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
BOOST_IMPORT_TEMPLATE1(template_name1) \
template<class T, class B> \
struct is_chained_base< ::boost::template_name1<T, B> > { \
typedef ::boost::detail::true_t value; \
};
// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
// can be used for specifying both 1-argument and 2-argument forms. Requires the
// existence of two previously defined class templates named '<template_name>1'
// and '<template_name>2' which must implement the corresponding 1- and 2-
// argument forms.
//
// The template type parameter O == is_chained_base<U>::value is used to
// distinguish whether the 2nd argument to <template_name> is being used for
// base class chaining from another boost operator template or is describing a
// 2nd operand type. O == true_t only when U is actually an another operator
// template from the library. Partial specialization is used to select an
// implementation in terms of either '<template_name>1' or '<template_name>2'.
//
# define BOOST_OPERATOR_TEMPLATE(template_name) \
template <class T \
,class U = T \
,class B = ::boost::detail::empty_base<T> \
,class O = typename is_chained_base<U>::value \
> \
struct template_name : template_name##2<T, U, B> {}; \
\
template<class T, class U, class B> \
struct template_name<T, U, B, ::boost::detail::true_t> \
: template_name##1<T, U> {}; \
\
template <class T, class B> \
struct template_name<T, T, B, ::boost::detail::false_t> \
: template_name##1<T, B> {}; \
\
template<class T, class U, class B, class O> \
struct is_chained_base< ::boost::template_name<T, U, B, O> > { \
typedef ::boost::detail::true_t value; \
}; \
\
BOOST_OPERATOR_TEMPLATE2(template_name##2) \
BOOST_OPERATOR_TEMPLATE1(template_name##1)
namespace boost {
BOOST_OPERATOR_TEMPLATE(less_than_comparable)
BOOST_OPERATOR_TEMPLATE(equality_comparable)
BOOST_OPERATOR_TEMPLATE(multipliable)
BOOST_OPERATOR_TEMPLATE(addable)
BOOST_OPERATOR_TEMPLATE(subtractable)
BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
BOOST_OPERATOR_TEMPLATE(dividable)
BOOST_OPERATOR_TEMPLATE2(dividable2_left)
BOOST_OPERATOR_TEMPLATE(modable)
BOOST_OPERATOR_TEMPLATE2(modable2_left)
BOOST_OPERATOR_TEMPLATE(xorable)
BOOST_OPERATOR_TEMPLATE(andable)
BOOST_OPERATOR_TEMPLATE(orable)
BOOST_OPERATOR_TEMPLATE1(incrementable)
BOOST_OPERATOR_TEMPLATE1(decrementable)
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
BOOST_OPERATOR_TEMPLATE3(indexable)
BOOST_OPERATOR_TEMPLATE(left_shiftable)
BOOST_OPERATOR_TEMPLATE(right_shiftable)
BOOST_OPERATOR_TEMPLATE(equivalent)
BOOST_OPERATOR_TEMPLATE(partially_ordered)
BOOST_OPERATOR_TEMPLATE(totally_ordered)
BOOST_OPERATOR_TEMPLATE(additive)
BOOST_OPERATOR_TEMPLATE(multiplicative)
BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
BOOST_OPERATOR_TEMPLATE(arithmetic)
BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
BOOST_OPERATOR_TEMPLATE(bitwise)
BOOST_OPERATOR_TEMPLATE1(unit_steppable)
BOOST_OPERATOR_TEMPLATE(shiftable)
BOOST_OPERATOR_TEMPLATE(ring_operators)
BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
BOOST_OPERATOR_TEMPLATE(field_operators)
BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
BOOST_OPERATOR_TEMPLATE(euclidean_ring_operators)
BOOST_OPERATOR_TEMPLATE(ordered_euclidean_ring_operators)
BOOST_OPERATOR_TEMPLATE2(input_iteratable)
BOOST_OPERATOR_TEMPLATE1(output_iteratable)
BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
#undef BOOST_OPERATOR_TEMPLATE
#undef BOOST_OPERATOR_TEMPLATE4
#undef BOOST_OPERATOR_TEMPLATE3
#undef BOOST_OPERATOR_TEMPLATE2
#undef BOOST_OPERATOR_TEMPLATE1
#undef BOOST_IMPORT_TEMPLATE1
#undef BOOST_IMPORT_TEMPLATE2
#undef BOOST_IMPORT_TEMPLATE3
#undef BOOST_IMPORT_TEMPLATE4
// The following 'operators' classes can only be used portably if the derived class
// declares ALL of the required member operators.
template <class T, class U>
struct operators2
: totally_ordered2<T,U
, integer_arithmetic2<T,U
, bitwise2<T,U
> > > {};
template <class T, class U = T>
struct operators : operators2<T, U> {};
template <class T> struct operators<T, T>
: totally_ordered<T
, integer_arithmetic<T
, bitwise<T
, unit_steppable<T
> > > > {};
// Iterator helper classes (contributed by Jeremy Siek) -------------------//
// (Input and output iterator helpers contributed by Daryle Walker) -------//
// (Changed to use combined operator classes by Daryle Walker) ------------//
template <class T,
class V,
class D = std::ptrdiff_t,
class P = V const *,
class R = V const &>
struct input_iterator_helper
: input_iteratable<T, P
, std::iterator<std::input_iterator_tag, V, D, P, R
> > {};
template<class T>
struct output_iterator_helper
: output_iteratable<T
, std::iterator<std::output_iterator_tag, void, void, void, void
> >
{
T& operator*() { return static_cast<T&>(*this); }
T& operator++() { return static_cast<T&>(*this); }
};
template <class T,
class V,
class D = std::ptrdiff_t,
class P = V*,
class R = V&>
struct forward_iterator_helper
: forward_iteratable<T, P
, std::iterator<std::forward_iterator_tag, V, D, P, R
> > {};
template <class T,
class V,
class D = std::ptrdiff_t,
class P = V*,
class R = V&>
struct bidirectional_iterator_helper
: bidirectional_iteratable<T, P
, std::iterator<std::bidirectional_iterator_tag, V, D, P, R
> > {};
template <class T,
class V,
class D = std::ptrdiff_t,
class P = V*,
class R = V&>
struct random_access_iterator_helper
: random_access_iteratable<T, P, D, R
, std::iterator<std::random_access_iterator_tag, V, D, P, R
> >
{
friend D requires_difference_operator(const T& x, const T& y) {
return x - y;
}
}; // random_access_iterator_helper
} // namespace boost
#if defined(__sgi) && !defined(__GNUC__)
#pragma reset woff 1234
#endif
#endif // BOOST_OPERATORS_V1_HPP

View File

@ -14,8 +14,8 @@
#include <boost/utility/binary.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/utility/identity_type.hpp>
#include <boost/checked_delete.hpp>
#include <boost/core/checked_delete.hpp>
#include <boost/core/noncopyable.hpp>
#include <boost/next_prior.hpp>
#include <boost/noncopyable.hpp>
#endif // BOOST_UTILITY_HPP

View File

@ -47,11 +47,11 @@
// {}
// This macro should only persist within this file.
#define BOOST_PRIVATE_CTR_DEF( z, n, data ) \
template < BOOST_PP_ENUM_PARAMS(n, typename T) > \
explicit base_from_member( BOOST_PP_ENUM_BINARY_PARAMS(n, T, x) ) \
: member( BOOST_PP_ENUM_PARAMS(n, x) ) \
{} \
#define BOOST_PRIVATE_CTR_DEF( z, n, data ) \
template < BOOST_PP_ENUM_PARAMS(n, typename T) > \
base_from_member( BOOST_PP_ENUM_BINARY_PARAMS(n, T, x) ) \
: member( BOOST_PP_ENUM_PARAMS(n, x) ) \
{} \
/**/
@ -142,7 +142,8 @@ protected:
: member()
{}
BOOST_PP_REPEAT_FROM_TO( 1, BOOST_PP_INC(BOOST_BASE_FROM_MEMBER_MAX_ARITY),
template < typename T0 > explicit base_from_member( T0 x0 ) : member( x0 ) {}
BOOST_PP_REPEAT_FROM_TO( 2, BOOST_PP_INC(BOOST_BASE_FROM_MEMBER_MAX_ARITY),
BOOST_PRIVATE_CTR_DEF, _ )
#endif

View File

@ -33,8 +33,12 @@ bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y )
}
template<class OptionalPointee>
struct equal_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
struct equal_pointees_t
{
typedef bool result_type;
typedef OptionalPointee first_argument_type;
typedef OptionalPointee second_argument_type;
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
{ return equal_pointees(x,y) ; }
} ;
@ -56,8 +60,12 @@ bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y )
}
template<class OptionalPointee>
struct less_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
struct less_pointees_t
{
typedef bool result_type;
typedef OptionalPointee first_argument_type;
typedef OptionalPointee second_argument_type;
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
{ return less_pointees(x,y) ; }
} ;

View File

@ -201,6 +201,11 @@ struct tr1_result_of_impl<F, FArgs, false>
#define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_RESULT_OF_NUM_ARGS,<boost/utility/detail/result_of_iterate.hpp>))
#include BOOST_PP_ITERATE()
#if 0
// inform dependency trackers, as they can't see through macro includes
#include <boost/utility/detail/result_of_iterate.hpp>
#endif
#else
# define BOOST_NO_RESULT_OF 1
#endif

View File

@ -1,5 +1,5 @@
/*
Copyright (c) Marshall Clow 2012-2012.
Copyright (c) Marshall Clow 2012-2015.
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)
@ -27,6 +27,11 @@
#include <string>
#include <iosfwd>
#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406)
// GCC 4.6 cannot handle a defaulted function with noexcept specifier
#define BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
#endif
namespace boost {
namespace detail {
@ -57,37 +62,55 @@ namespace boost {
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
// construct/copy
BOOST_CONSTEXPR basic_string_ref ()
BOOST_CONSTEXPR basic_string_ref () BOOST_NOEXCEPT
: ptr_(NULL), len_(0) {}
BOOST_CONSTEXPR basic_string_ref (const basic_string_ref &rhs)
// by defaulting these functions, basic_string_ref becomes
// trivially copy/move constructible.
BOOST_CONSTEXPR basic_string_ref (const basic_string_ref &rhs) BOOST_NOEXCEPT
#ifndef BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
= default;
#else
: ptr_(rhs.ptr_), len_(rhs.len_) {}
#endif
basic_string_ref& operator=(const basic_string_ref &rhs) {
basic_string_ref& operator=(const basic_string_ref &rhs) BOOST_NOEXCEPT
#ifndef BOOST_STRING_REF_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
= default;
#else
{
ptr_ = rhs.ptr_;
len_ = rhs.len_;
return *this;
}
#endif
basic_string_ref(const charT* str)
basic_string_ref(const charT* str) BOOST_NOEXCEPT
: ptr_(str), len_(traits::length(str)) {}
template<typename Allocator>
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str)
: ptr_(str.data()), len_(str.length()) {}
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len)
// #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
// // Constructing a string_ref from a temporary string is a bad idea
// template<typename Allocator>
// basic_string_ref( std::basic_string<charT, traits, Allocator>&&)
// = delete;
// #endif
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len) BOOST_NOEXCEPT
: ptr_(str), len_(len) {}
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
template<typename Allocator>
explicit operator std::basic_string<charT, traits, Allocator>() const {
return std::basic_string<charT, traits, Allocator> ( ptr_, len_ );
return std::basic_string<charT, traits, Allocator> ( begin(), end());
}
#endif
std::basic_string<charT, traits> to_string () const {
return std::basic_string<charT, traits> ( ptr_, len_ );
return std::basic_string<charT, traits> ( begin(), end());
}
// iterators
@ -139,9 +162,7 @@ namespace boost {
basic_string_ref substr(size_type pos, size_type n=npos) const {
if ( pos > size())
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_ref::substr" ) );
if ( n == npos || pos + n > size())
n = size () - pos;
return basic_string_ref ( data() + pos, n );
return basic_string_ref(data() + pos, (std::min)(size() - pos, n));
}
int compare(basic_string_ref x) const {
@ -174,13 +195,13 @@ namespace boost {
size_type rfind(basic_string_ref s) const {
const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (),
s.crbegin (), s.crend (), traits::eq );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
return iter == this->crend () ? npos : (std::distance(iter, this->crend()) - s.size());
}
size_type rfind(charT c) const {
const_reverse_iterator iter = std::find_if ( this->crbegin (), this->crend (),
detail::string_ref_traits_eq<charT, traits> ( c ));
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
return iter == this->crend () ? npos : (this->size() - 1 - std::distance(this->crbegin(), iter));
}
size_type find_first_of(charT c) const { return find (c); }
@ -195,7 +216,7 @@ namespace boost {
size_type find_last_of(basic_string_ref s) const {
const_reverse_iterator iter = std::find_first_of
( this->crbegin (), this->crend (), s.cbegin (), s.cend (), traits::eq );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
return iter == this->crend () ? npos : (this->size() - 1 - std::distance(this->crbegin(), iter));
}
size_type find_first_not_of(basic_string_ref s) const {
@ -212,21 +233,17 @@ namespace boost {
size_type find_last_not_of(basic_string_ref s) const {
const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
return iter == this->crend () ? npos : (this->size() - 1 - std::distance(this->crbegin(), iter));
}
size_type find_last_not_of(charT c) const {
for ( const_reverse_iterator iter = this->crbegin (); iter != this->crend (); ++iter )
if ( !traits::eq ( c, *iter ))
return reverse_distance ( this->crbegin (), iter );
return this->size() - 1 - std::distance(this->crbegin(), iter);
return npos;
}
private:
template <typename r_iter>
size_type reverse_distance ( r_iter first, r_iter last ) const {
return len_ - 1 - std::distance ( first, last );
}
template <typename Iterator>
Iterator find_not_of ( Iterator first, Iterator last, basic_string_ref s ) const {
@ -405,7 +422,7 @@ namespace boost {
namespace detail {
template<class charT, class traits>
inline void insert_fill_chars(std::basic_ostream<charT, traits>& os, std::size_t n) {
inline void sr_insert_fill_chars(std::basic_ostream<charT, traits>& os, std::size_t n) {
enum { chunk_size = 8 };
charT fill_chars[chunk_size];
std::fill_n(fill_chars, static_cast< std::size_t >(chunk_size), os.fill());
@ -416,19 +433,19 @@ namespace boost {
}
template<class charT, class traits>
void insert_aligned(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
void sr_insert_aligned(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) {
const std::size_t size = str.size();
const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - size;
const bool align_left = (os.flags() & std::basic_ostream<charT, traits>::adjustfield) == std::basic_ostream<charT, traits>::left;
if (!align_left) {
detail::insert_fill_chars(os, alignment_size);
detail::sr_insert_fill_chars(os, alignment_size);
if (os.good())
os.write(str.data(), size);
}
else {
os.write(str.data(), size);
if (os.good())
detail::insert_fill_chars(os, alignment_size);
detail::sr_insert_fill_chars(os, alignment_size);
}
}
@ -444,7 +461,7 @@ namespace boost {
if (w <= size)
os.write(str.data(), size);
else
detail::insert_aligned(os, str);
detail::sr_insert_aligned(os, str);
os.width(0);
}
return os;

View File

@ -0,0 +1,690 @@
/*
Copyright (c) Marshall Clow 2012-2015.
Copyright (c) Beman Dawes 2015
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)
For more information, see http://www.boost.org
Based on the StringRef implementation in LLVM (http://llvm.org) and
N3422 by Jeffrey Yasskin
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
Updated July 2015 to reflect the Library Fundamentals TS
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html
*/
#ifndef BOOST_STRING_VIEW_HPP
#define BOOST_STRING_VIEW_HPP
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/utility/string_view_fwd.hpp>
#include <boost/throw_exception.hpp>
#include <cstddef>
#include <stdexcept>
#include <algorithm>
#include <iterator>
#include <string>
#include <cstring>
#include <iosfwd>
#if defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || (defined(BOOST_GCC) && ((BOOST_GCC+0) / 100) <= 406)
// GCC 4.6 cannot handle a defaulted function with noexcept specifier
#define BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
#endif
namespace boost {
namespace detail {
// A helper functor because sometimes we don't have lambdas
template <typename charT, typename traits>
class string_view_traits_eq {
public:
string_view_traits_eq ( charT ch ) : ch_(ch) {}
bool operator()( charT val ) const { return traits::eq (ch_, val); }
charT ch_;
};
}
template<typename charT, typename traits> // traits defaulted in string_view_fwd.hpp
class basic_string_view {
public:
// types
typedef traits traits_type;
typedef charT value_type;
typedef charT* pointer;
typedef const charT* const_pointer;
typedef charT& reference;
typedef const charT& const_reference;
typedef const_pointer const_iterator; // impl-defined
typedef const_iterator iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
typedef const_reverse_iterator reverse_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
// construct/copy
BOOST_CONSTEXPR basic_string_view() BOOST_NOEXCEPT
: ptr_(NULL), len_(0) {}
// by defaulting these functions, basic_string_ref becomes
// trivially copy/move constructible.
BOOST_CONSTEXPR basic_string_view(const basic_string_view &rhs) BOOST_NOEXCEPT
#ifndef BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
= default;
#else
: ptr_(rhs.ptr_), len_(rhs.len_) {}
#endif
basic_string_view& operator=(const basic_string_view &rhs) BOOST_NOEXCEPT
#ifndef BOOST_STRING_VIEW_NO_CXX11_DEFAULTED_NOEXCEPT_FUNCTIONS
= default;
#else
{
ptr_ = rhs.ptr_;
len_ = rhs.len_;
return *this;
}
#endif
template<typename Allocator>
basic_string_view(const std::basic_string<charT, traits, Allocator>& str) BOOST_NOEXCEPT
: ptr_(str.data()), len_(str.length()) {}
// #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
// // Constructing a string_view from a temporary string is a bad idea
// template<typename Allocator>
// basic_string_view( std::basic_string<charT, traits, Allocator>&&)
// = delete;
// #endif
BOOST_CONSTEXPR basic_string_view(const charT* str)
: ptr_(str), len_(traits::length(str)) {}
BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len)
: ptr_(str), len_(len) {}
// iterators
BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return ptr_; }
BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT { return ptr_; }
BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return ptr_ + len_; }
BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT { return ptr_ + len_; }
const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); }
const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); }
// capacity
BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return len_; }
BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT { return len_; }
BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT { return len_; }
BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT { return len_ == 0; }
// element access
BOOST_CONSTEXPR const_reference operator[](size_type pos) const BOOST_NOEXCEPT { return ptr_[pos]; }
BOOST_CONSTEXPR const_reference at(size_t pos) const {
return pos >= len_ ? BOOST_THROW_EXCEPTION(std::out_of_range("boost::string_view::at")), ptr_[0] : ptr_[pos];
}
BOOST_CONSTEXPR const_reference front() const { return ptr_[0]; }
BOOST_CONSTEXPR const_reference back() const { return ptr_[len_-1]; }
BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return ptr_; }
// modifiers
void clear() BOOST_NOEXCEPT { len_ = 0; } // Boost extension
BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n) {
if ( n > len_ )
n = len_;
ptr_ += n;
len_ -= n;
}
BOOST_CXX14_CONSTEXPR void remove_suffix(size_type n) {
if ( n > len_ )
n = len_;
len_ -= n;
}
BOOST_CXX14_CONSTEXPR void swap(basic_string_view& s) BOOST_NOEXCEPT {
std::swap(ptr_, s.ptr_);
std::swap(len_, s.len_);
}
// basic_string_view string operations
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
template<typename Allocator>
explicit operator std::basic_string<charT, traits, Allocator>() const {
return std::basic_string<charT, traits, Allocator>(begin(), end());
}
#endif
#ifndef BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
template<typename Allocator = std::allocator<charT> >
std::basic_string<charT, traits, Allocator> to_string(const Allocator& a = Allocator()) const {
return std::basic_string<charT, traits, Allocator>(begin(), end(), a);
}
#else
std::basic_string<charT, traits> to_string() const {
return std::basic_string<charT, traits>(begin(), end());
}
template<typename Allocator>
std::basic_string<charT, traits, Allocator> to_string(const Allocator& a) const {
return std::basic_string<charT, traits, Allocator>(begin(), end(), a);
}
#endif
size_type copy(charT* s, size_type n, size_type pos=0) const {
if (pos > size())
BOOST_THROW_EXCEPTION(std::out_of_range("string_view::copy" ));
size_type rlen = (std::min)(n, len_ - pos);
traits_type::copy(s, data() + pos, rlen);
return rlen;
}
BOOST_CXX14_CONSTEXPR basic_string_view substr(size_type pos, size_type n=npos) const {
if ( pos > size())
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_view::substr" ) );
return basic_string_view(data() + pos, (std::min)(size() - pos, n));
}
BOOST_CXX14_CONSTEXPR int compare(basic_string_view x) const BOOST_NOEXCEPT {
const int cmp = traits::compare(ptr_, x.ptr_, (std::min)(len_, x.len_));
return cmp != 0 ? cmp : (len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1);
}
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, basic_string_view x)
const BOOST_NOEXCEPT {
return substr(pos1, n1).compare(x);
}
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1,
basic_string_view x, size_type pos2, size_type n2) const {
return substr(pos1, n1).compare(x.substr(pos2, n2));
}
BOOST_CXX14_CONSTEXPR int compare(const charT* x) const {
return compare(basic_string_view(x));
}
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, const charT* x) const {
return substr(pos1, n1).compare(basic_string_view(x));
}
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1,
const charT* x, size_type n2) const {
return substr(pos1, n1).compare(basic_string_view(x, n2));
}
// Searches
BOOST_CONSTEXPR bool starts_with(charT c) const BOOST_NOEXCEPT { // Boost extension
return !empty() && traits::eq(c, front());
}
BOOST_CONSTEXPR bool starts_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension
return len_ >= x.len_ && traits::compare(ptr_, x.ptr_, x.len_) == 0;
}
BOOST_CONSTEXPR bool ends_with(charT c) const BOOST_NOEXCEPT { // Boost extension
return !empty() && traits::eq(c, back());
}
BOOST_CONSTEXPR bool ends_with(basic_string_view x) const BOOST_NOEXCEPT { // Boost extension
return len_ >= x.len_ &&
traits::compare(ptr_ + len_ - x.len_, x.ptr_, x.len_) == 0;
}
// find
BOOST_CXX14_CONSTEXPR size_type find(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
if (pos > size())
return npos;
if (s.empty())
return pos;
const_iterator iter = std::search(this->cbegin() + pos, this->cend(),
s.cbegin (), s.cend (), traits::eq);
return iter == this->cend () ? npos : std::distance(this->cbegin (), iter);
}
BOOST_CXX14_CONSTEXPR size_type find(charT c, size_type pos = 0) const BOOST_NOEXCEPT
{ return find(basic_string_view(&c, 1), pos); }
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
{ return find(basic_string_view(s, n), pos); }
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
{ return find(basic_string_view(s), pos); }
// rfind
BOOST_CXX14_CONSTEXPR size_type rfind(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
if (len_ < s.len_)
return npos;
if (pos > len_ - s.len_)
pos = len_ - s.len_;
if (s.len_ == 0u) // an empty string is always found
return pos;
for (const charT* cur = ptr_ + pos; ; --cur) {
if (traits::compare(cur, s.ptr_, s.len_) == 0)
return cur - ptr_;
if (cur == ptr_)
return npos;
};
}
BOOST_CXX14_CONSTEXPR size_type rfind(charT c, size_type pos = npos) const BOOST_NOEXCEPT
{ return rfind(basic_string_view(&c, 1), pos); }
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
{ return rfind(basic_string_view(s, n), pos); }
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
{ return rfind(basic_string_view(s), pos); }
// find_first_of
BOOST_CXX14_CONSTEXPR size_type find_first_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
if (pos >= len_ || s.len_ == 0)
return npos;
const_iterator iter = std::find_first_of
(this->cbegin () + pos, this->cend (), s.cbegin (), s.cend (), traits::eq);
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
}
BOOST_CXX14_CONSTEXPR size_type find_first_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT
{ return find_first_of(basic_string_view(&c, 1), pos); }
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
{ return find_first_of(basic_string_view(s, n), pos); }
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
{ return find_first_of(basic_string_view(s), pos); }
// find_last_of
BOOST_CXX14_CONSTEXPR size_type find_last_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
if (s.len_ == 0u)
return npos;
if (pos >= len_)
pos = 0;
else
pos = len_ - (pos+1);
const_reverse_iterator iter = std::find_first_of
( this->crbegin () + pos, this->crend (), s.cbegin (), s.cend (), traits::eq );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
}
BOOST_CXX14_CONSTEXPR size_type find_last_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT
{ return find_last_of(basic_string_view(&c, 1), pos); }
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
{ return find_last_of(basic_string_view(s, n), pos); }
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
{ return find_last_of(basic_string_view(s), pos); }
// find_first_not_of
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
if (pos >= len_)
return npos;
if (s.len_ == 0)
return pos;
const_iterator iter = find_not_of ( this->cbegin () + pos, this->cend (), s );
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
}
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT
{ return find_first_not_of(basic_string_view(&c, 1), pos); }
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
{ return find_first_not_of(basic_string_view(s, n), pos); }
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos = 0) const BOOST_NOEXCEPT
{ return find_first_not_of(basic_string_view(s), pos); }
// find_last_not_of
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
if (pos >= len_)
pos = len_ - 1;
if (s.len_ == 0u)
return pos;
pos = len_ - (pos+1);
const_reverse_iterator iter = find_not_of ( this->crbegin () + pos, this->crend (), s );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
}
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT
{ return find_last_not_of(basic_string_view(&c, 1), pos); }
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos, size_type n) const BOOST_NOEXCEPT
{ return find_last_not_of(basic_string_view(s, n), pos); }
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos = npos) const BOOST_NOEXCEPT
{ return find_last_not_of(basic_string_view(s), pos); }
private:
template <typename r_iter>
size_type reverse_distance(r_iter first, r_iter last) const BOOST_NOEXCEPT {
// Portability note here: std::distance is not NOEXCEPT, but calling it with a string_view::reverse_iterator will not throw.
return len_ - 1 - std::distance ( first, last );
}
template <typename Iterator>
Iterator find_not_of(Iterator first, Iterator last, basic_string_view s) const BOOST_NOEXCEPT {
for (; first != last ; ++first)
if ( 0 == traits::find(s.ptr_, s.len_, *first))
return first;
return last;
}
const charT *ptr_;
std::size_t len_;
};
// Comparison operators
// Equality
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
if (x.size () != y.size ()) return false;
return x.compare(y) == 0;
}
// Inequality
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
if ( x.size () != y.size ()) return true;
return x.compare(y) != 0;
}
// Less than
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return x.compare(y) < 0;
}
// Greater than
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return x.compare(y) > 0;
}
// Less than or equal to
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return x.compare(y) <= 0;
}
// Greater than or equal to
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return x.compare(y) >= 0;
}
// "sufficient additional overloads of comparison functions"
template<typename charT, typename traits, typename Allocator>
inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x,
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
return x == basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline BOOST_CXX14_CONSTEXPR bool operator==(const std::basic_string<charT, traits, Allocator> & x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) == y;
}
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator==(basic_string_view<charT, traits> x,
const charT * y) BOOST_NOEXCEPT {
return x == basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator==(const charT * x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) == y;
}
template<typename charT, typename traits, typename Allocator>
inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x,
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
return x != basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline BOOST_CXX14_CONSTEXPR bool operator!=(const std::basic_string<charT, traits, Allocator> & x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) != y;
}
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator!=(basic_string_view<charT, traits> x,
const charT * y) BOOST_NOEXCEPT {
return x != basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator!=(const charT * x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) != y;
}
template<typename charT, typename traits, typename Allocator>
inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x,
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
return x < basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline BOOST_CXX14_CONSTEXPR bool operator<(const std::basic_string<charT, traits, Allocator> & x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) < y;
}
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator<(basic_string_view<charT, traits> x,
const charT * y) BOOST_NOEXCEPT {
return x < basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator<(const charT * x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) < y;
}
template<typename charT, typename traits, typename Allocator>
inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x,
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
return x > basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline BOOST_CXX14_CONSTEXPR bool operator>(const std::basic_string<charT, traits, Allocator> & x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) > y;
}
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator>(basic_string_view<charT, traits> x,
const charT * y) BOOST_NOEXCEPT {
return x > basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator>(const charT * x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) > y;
}
template<typename charT, typename traits, typename Allocator>
inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x,
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
return x <= basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline BOOST_CXX14_CONSTEXPR bool operator<=(const std::basic_string<charT, traits, Allocator> & x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) <= y;
}
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator<=(basic_string_view<charT, traits> x,
const charT * y) BOOST_NOEXCEPT {
return x <= basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator<=(const charT * x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) <= y;
}
template<typename charT, typename traits, typename Allocator>
inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x,
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
return x >= basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits, typename Allocator>
inline BOOST_CXX14_CONSTEXPR bool operator>=(const std::basic_string<charT, traits, Allocator> & x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) >= y;
}
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator>=(basic_string_view<charT, traits> x,
const charT * y) BOOST_NOEXCEPT {
return x >= basic_string_view<charT, traits>(y);
}
template<typename charT, typename traits>
inline BOOST_CXX14_CONSTEXPR bool operator>=(const charT * x,
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
return basic_string_view<charT, traits>(x) >= y;
}
namespace detail {
template<class charT, class traits>
inline void sv_insert_fill_chars(std::basic_ostream<charT, traits>& os, std::size_t n) {
enum { chunk_size = 8 };
charT fill_chars[chunk_size];
std::fill_n(fill_chars, static_cast< std::size_t >(chunk_size), os.fill());
for (; n >= chunk_size && os.good(); n -= chunk_size)
os.write(fill_chars, static_cast< std::size_t >(chunk_size));
if (n > 0 && os.good())
os.write(fill_chars, n);
}
template<class charT, class traits>
void sv_insert_aligned(std::basic_ostream<charT, traits>& os, const basic_string_view<charT,traits>& str) {
const std::size_t size = str.size();
const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - size;
const bool align_left = (os.flags() & std::basic_ostream<charT, traits>::adjustfield) == std::basic_ostream<charT, traits>::left;
if (!align_left) {
detail::sv_insert_fill_chars(os, alignment_size);
if (os.good())
os.write(str.data(), size);
}
else {
os.write(str.data(), size);
if (os.good())
detail::sv_insert_fill_chars(os, alignment_size);
}
}
} // namespace detail
// Inserter
template<class charT, class traits>
inline std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os,
const basic_string_view<charT,traits>& str) {
if (os.good()) {
const std::size_t size = str.size();
const std::size_t w = static_cast< std::size_t >(os.width());
if (w <= size)
os.write(str.data(), size);
else
detail::sv_insert_aligned(os, str);
os.width(0);
}
return os;
}
#if 0
// numeric conversions
//
// These are short-term implementations.
// In a production environment, I would rather avoid the copying.
//
inline int stoi (string_view str, size_t* idx=0, int base=10) {
return std::stoi ( std::string(str), idx, base );
}
inline long stol (string_view str, size_t* idx=0, int base=10) {
return std::stol ( std::string(str), idx, base );
}
inline unsigned long stoul (string_view str, size_t* idx=0, int base=10) {
return std::stoul ( std::string(str), idx, base );
}
inline long long stoll (string_view str, size_t* idx=0, int base=10) {
return std::stoll ( std::string(str), idx, base );
}
inline unsigned long long stoull (string_view str, size_t* idx=0, int base=10) {
return std::stoull ( std::string(str), idx, base );
}
inline float stof (string_view str, size_t* idx=0) {
return std::stof ( std::string(str), idx );
}
inline double stod (string_view str, size_t* idx=0) {
return std::stod ( std::string(str), idx );
}
inline long double stold (string_view str, size_t* idx=0) {
return std::stold ( std::string(str), idx );
}
inline int stoi (wstring_view str, size_t* idx=0, int base=10) {
return std::stoi ( std::wstring(str), idx, base );
}
inline long stol (wstring_view str, size_t* idx=0, int base=10) {
return std::stol ( std::wstring(str), idx, base );
}
inline unsigned long stoul (wstring_view str, size_t* idx=0, int base=10) {
return std::stoul ( std::wstring(str), idx, base );
}
inline long long stoll (wstring_view str, size_t* idx=0, int base=10) {
return std::stoll ( std::wstring(str), idx, base );
}
inline unsigned long long stoull (wstring_view str, size_t* idx=0, int base=10) {
return std::stoull ( std::wstring(str), idx, base );
}
inline float stof (wstring_view str, size_t* idx=0) {
return std::stof ( std::wstring(str), idx );
}
inline double stod (wstring_view str, size_t* idx=0) {
return std::stod ( std::wstring(str), idx );
}
inline long double stold (wstring_view str, size_t* idx=0) {
return std::stold ( std::wstring(str), idx );
}
#endif
}
#if 0
namespace std {
// Hashing
template<> struct hash<boost::string_view>;
template<> struct hash<boost::u16string_view>;
template<> struct hash<boost::u32string_view>;
template<> struct hash<boost::wstring_view>;
}
#endif
#endif

View File

@ -0,0 +1,39 @@
/*
Copyright (c) Marshall Clow 2012-2012.
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)
For more information, see http://www.boost.org
Based on the StringRef implementation in LLVM (http://llvm.org) and
N3422 by Jeffrey Yasskin
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
Updated July 2015 to reflect the Library Fundamentals TS
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html
*/
#ifndef BOOST_STRING_VIEW_FWD_HPP
#define BOOST_STRING_VIEW_FWD_HPP
#include <boost/config.hpp>
#include <string>
namespace boost {
template<typename charT, typename traits = std::char_traits<charT> > class basic_string_view;
typedef basic_string_view<char, std::char_traits<char> > string_view;
typedef basic_string_view<wchar_t, std::char_traits<wchar_t> > wstring_view;
#ifndef BOOST_NO_CXX11_CHAR16_T
typedef basic_string_view<char16_t, std::char_traits<char16_t> > u16string_view;
#endif
#ifndef BOOST_NO_CXX11_CHAR32_T
typedef basic_string_view<char32_t, std::char_traits<char32_t> > u32string_view;
#endif
}
#endif

113
meta/libraries.json Normal file
View File

@ -0,0 +1,113 @@
[
{
"key": "utility",
"name": "Utility",
"authors": [
"Dave Abrahams and others"
],
"description": "Class noncopyable plus checked_delete(), checked_array_delete(), next(), prior() function templates, plus base-from-member idiom.",
"documentation": "utility.htm",
"category": [
"Algorithms",
"Function-objects",
"Memory",
"Miscellaneous",
"Patterns"
]
},
{
"key": "utility/call_traits",
"name": "Call Traits",
"authors": [
"John Maddock, Howard Hinnant, et al"
],
"description": "Defines types for passing parameters.",
"documentation": "call_traits.htm",
"category": [
"Generic"
]
},
{
"key": "utility/compressed_pair",
"name": "Compressed Pair",
"authors": [
"John Maddock, Howard Hinnant, et al"
],
"description": "Empty member optimization.",
"documentation": "compressed_pair.htm",
"category": [
"Data",
"Patterns"
]
},
{
"key": "utility/identity_type",
"name": "Identity Type",
"authors": [
"Lorenzo Caminiti"
],
"description": "Wrap types within round parenthesis so they can always be passed as macro parameters.",
"documentation": "identity_type/",
"category": [
"Preprocessor"
],
"maintainers": [
"Lorenzo Caminiti <lorcaminiti -at- gmail.com>"
]
},
{
"key": "utility/in_place_factories",
"name": "In Place Factory, Typed In Place Factory",
"authors": [
"Fernando Cacciola"
],
"description": "Generic in-place construction of contained objects with a variadic argument-list.",
"documentation": "in_place_factories.html",
"category": [
"Generic"
]
},
{
"key": "utility/operators",
"name": "Operators",
"authors": [
"Dave Abrahams",
"Jeremy Siek"
],
"description": "Templates ease arithmetic classes and iterators.",
"documentation": "operators.htm",
"category": [
"Generic",
"Iterators",
"Math"
],
"maintainers": [
"Daniel Frey <d.frey -at- gmx.de>"
]
},
{
"key": "utility/result_of",
"name": "Result Of",
"description": "Determines the type of a function call expression.",
"documentation": "utility.htm#result_of",
"category": [
"Function-objects"
],
"authors": "",
"maintainers": [
"Daniel Walker <daniel.j.walker -at- gmail.com>"
]
},
{
"key": "utility/value_initialized",
"name": "Value Initialized",
"authors": [
"Fernando Cacciola"
],
"description": "Wrapper for uniform-syntax value initialization, based on the original idea of David Abrahams.",
"documentation": "value_init.htm",
"category": [
"Miscellaneous"
]
}
]

View File

@ -11,34 +11,46 @@ import testing ;
alias unit_test_framework
: # sources
/boost//unit_test_framework
;
# Please keep the tests ordered by filename
test-suite utility
:
[ run ../base_from_member_test.cpp ]
[ run ../base_from_member_ref_test.cpp ]
[ run ../binary_test.cpp ]
[ run ../call_traits_test.cpp : -u ]
[ run ../compressed_pair_test.cpp ../../test/build//boost_test_exec_monitor/<link>static : -u ]
[ run ../iterators_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ]
[ run next_prior_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ]
[ run ../numeric_traits_test.cpp ]
[ run ../operators_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ]
[ compile result_of_test.cpp ]
[ run ../shared_iterator_test.cpp ]
[ run string_ref_test1.cpp unit_test_framework ]
[ run string_ref_test2.cpp unit_test_framework ]
[ run string_ref_test_io.cpp unit_test_framework ]
[ run ../value_init_test.cpp ]
[ run ../value_init_workaround_test.cpp ]
[ run ../initialized_test.cpp ]
[ compile-fail ../value_init_test_fail1.cpp ]
[ compile-fail ../value_init_test_fail2.cpp ]
[ compile-fail ../value_init_test_fail3.cpp ]
[ compile-fail ../initialized_test_fail1.cpp ]
[ compile-fail ../initialized_test_fail2.cpp ]
[ run ../generator_iterator_test.cpp ]
;
run base_from_member_test.cpp ;
run base_from_member_ref_test.cpp ;
run binary_test.cpp ;
run call_traits_test.cpp : -u ;
run compressed_pair_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ;
run iterators_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ;
run next_prior_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ;
run numeric_traits_test.cpp ;
run operators_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ;
compile result_of_test.cpp ;
run shared_iterator_test.cpp ;
# compile-fail string_ref_from_rvalue.cpp ;
run string_ref_test1.cpp unit_test_framework ;
run string_ref_test2.cpp unit_test_framework ;
run string_ref_test_io.cpp unit_test_framework ;
# compile-fail string_view_from_rvalue.cpp ;
compile string_view_constexpr_test1.cpp ;
run string_view_test1.cpp unit_test_framework ;
run string_view_test2.cpp unit_test_framework ;
run string_view_test_io.cpp unit_test_framework ;
run value_init_test.cpp ;
run value_init_workaround_test.cpp ;
run initialized_test.cpp ;
compile-fail value_init_test_fail1.cpp ;
compile-fail value_init_test_fail2.cpp ;
compile-fail value_init_test_fail3.cpp ;
compile-fail initialized_test_fail1.cpp ;
compile-fail initialized_test_fail2.cpp ;
run generator_iterator_test.cpp ;

View File

@ -18,7 +18,7 @@
#include <boost/utility/base_from_member.hpp> // for boost::base_from_member
#include <functional> // for std::binary_function, std::less
#include <functional> // for std::less
#include <iostream> // for std::cout (std::ostream, std::endl indirectly)
#include <set> // for std::set
#include <typeinfo> // for std::type_info
@ -46,7 +46,6 @@ template < typename T >
// A custom comparison type is needed
struct object_id_compare
: std::binary_function<object_id, object_id, bool>
{
bool operator ()( object_id const &a, object_id const &b ) const;

View File

@ -66,14 +66,39 @@ bool minus_n_test(RandomAccessIterator first, RandomAccessIterator last, Bidirec
return std::distance(i, last) == std::distance(j, last2);
}
template<class Iterator, class Distance>
bool minus_n_unsigned_test(Iterator first, Iterator last, Distance size)
{
Iterator i = boost::prior(last, size);
return i == first;
}
int test_main(int, char*[])
{
std::vector<int> x(8);
std::list<int> y(x.begin(), x.end());
// Tests with iterators
BOOST_REQUIRE(plus_one_test(x.begin(), x.end(), y.begin()));
BOOST_REQUIRE(plus_n_test(x.begin(), x.end(), y.begin()));
BOOST_REQUIRE(minus_one_test(x.begin(), x.end(), y.end()));
BOOST_REQUIRE(minus_n_test(x.begin(), x.end(), y.end()));
BOOST_REQUIRE(minus_n_unsigned_test(x.begin(), x.end(), x.size()));
BOOST_REQUIRE(minus_n_unsigned_test(y.begin(), y.end(), y.size()));
BOOST_REQUIRE(plus_one_test(x.rbegin(), x.rend(), y.begin()));
BOOST_REQUIRE(plus_n_test(x.rbegin(), x.rend(), y.begin()));
BOOST_REQUIRE(minus_one_test(x.rbegin(), x.rend(), y.end()));
BOOST_REQUIRE(minus_n_test(x.rbegin(), x.rend(), y.end()));
BOOST_REQUIRE(minus_n_unsigned_test(x.rbegin(), x.rend(), x.size()));
BOOST_REQUIRE(minus_n_unsigned_test(x.rbegin(), x.rend(), y.size()));
// Tests with integers
BOOST_REQUIRE(boost::next(5) == 6);
BOOST_REQUIRE(boost::next(5, 7) == 12);
BOOST_REQUIRE(boost::prior(5) == 4);
BOOST_REQUIRE(boost::prior(5, 7) == -2);
BOOST_REQUIRE(boost::prior(5, 7u) == -2);
return 0;
}

View File

@ -38,11 +38,9 @@ namespace
int true_value(int x) { return x; }
long true_value(long x) { return x; }
signed char true_value(signed char x) { return x; }
short true_value(short x) { return x; }
unsigned int true_value(unsigned int x) { return x; }
unsigned long true_value(unsigned long x) { return x; }
unsigned char true_value(unsigned char x) { return x; }
unsigned short true_value(unsigned short x) { return x; }
// verify the minimum requirements for some operators
class convertible_to_bool

View File

@ -0,0 +1,28 @@
/*
Copyright (c) Marshall Clow 2017.
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)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <algorithm>
#include <string>
#include <boost/utility/string_ref.hpp>
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
#error "Unsupported test"
#endif
#include "boost/test/minimal.hpp"
std::string makeatemp() { return "abc"; }
int test_main(int, char **)
{
boost::basic_string_ref<char> sv(makeatemp());
return 0;
}

View File

@ -18,7 +18,7 @@
typedef boost::string_ref string_ref;
void ends_with ( const char *arg ) {
const size_t sz = strlen ( arg );
const size_t sz = std::strlen ( arg );
string_ref sr ( arg );
string_ref sr2 ( arg );
const char *p = arg;
@ -48,7 +48,7 @@ void ends_with ( const char *arg ) {
}
void starts_with ( const char *arg ) {
const size_t sz = strlen ( arg );
const size_t sz = std::strlen ( arg );
string_ref sr ( arg );
string_ref sr2 ( arg );
const char *p = arg + std::strlen ( arg ) - 1;
@ -83,7 +83,7 @@ void reverse ( const char *arg ) {
BOOST_CHECK ( std::equal ( sr1.begin (), sr1.end (), string2.begin ()));
}
// This helper function eliminates signed vs. unsigned warnings
// This helper function eliminates signed vs. unsigned warnings
string_ref::size_type ptr_diff ( const char *res, const char *base ) {
BOOST_CHECK ( res >= base );
return static_cast<string_ref::size_type> ( res - base );
@ -112,7 +112,7 @@ void find ( const char *arg ) {
++p;
}
// Look for pairs on characters (searching from the start)
// Look for pairs on characters (searching from the start)
sr1 = arg;
p = arg;
while ( *p && *(p+1)) {
@ -159,7 +159,7 @@ void find ( const char *arg ) {
// Find everything at the end
sr1 = arg;
p = arg + strlen ( arg ) - 1;
p = arg + std::strlen ( arg ) - 1;
while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.rfind(*p);
BOOST_CHECK ( pos == sr1.size () - 1 );
@ -180,7 +180,7 @@ void find ( const char *arg ) {
// Find everything at the end
sr1 = arg;
p = arg + strlen ( arg ) - 1;
p = arg + std::strlen ( arg ) - 1;
while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.find_last_of(*p);
BOOST_CHECK ( pos == sr1.size () - 1 );
@ -249,7 +249,7 @@ void to_string ( const char *arg ) {
str1.assign ( arg );
sr1 = arg;
// str2 = sr1.to_string<std::allocator<char> > ();
// str2 = sr1.to_string<std::allocator<char> > ();
str2 = sr1.to_string ();
BOOST_CHECK ( str1 == str2 );
@ -266,11 +266,11 @@ void compare ( const char *arg ) {
str1.assign ( arg );
sr1 = arg;
BOOST_CHECK ( sr1 == sr1); // compare string_ref and string_ref
BOOST_CHECK ( sr1 == str1); // compare string and string_ref
BOOST_CHECK ( str1 == sr1 ); // compare string_ref and string
BOOST_CHECK ( sr1 == arg ); // compare string_ref and pointer
BOOST_CHECK ( arg == sr1 ); // compare pointer and string_ref
BOOST_CHECK ( sr1 == sr1); // compare string_ref and string_ref
BOOST_CHECK ( sr1 == str1); // compare string and string_ref
BOOST_CHECK ( str1 == sr1 ); // compare string_ref and string
BOOST_CHECK ( sr1 == arg ); // compare string_ref and pointer
BOOST_CHECK ( arg == sr1 ); // compare pointer and string_ref
if ( sr1.size () > 0 ) {
(*str1.rbegin())++;

View File

@ -75,7 +75,6 @@ struct context
BOOST_AUTO_TEST_CASE_TEMPLATE(string_ref_output, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type;
@ -90,7 +89,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(string_ref_output, CharT, char_types)
BOOST_AUTO_TEST_CASE_TEMPLATE(padding, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type;
@ -134,7 +132,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(padding, CharT, char_types)
BOOST_AUTO_TEST_CASE_TEMPLATE(padding_fill, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type;
@ -153,7 +150,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(padding_fill, CharT, char_types)
BOOST_AUTO_TEST_CASE_TEMPLATE(alignment, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type;

View File

@ -0,0 +1,121 @@
/*
Copyright (c) Marshall Clow 2017-2017.
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)
For more information, see http://www.boost.org
*/
#include <new> // for placement new
#include <iostream>
#include <cstddef> // for NULL, std::size_t, std::ptrdiff_t
#include <cstring> // for std::strchr and std::strcmp
#include <cstdlib> // for std::malloc and std::free
#include <boost/config.hpp>
#include <boost/utility/string_view.hpp>
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#if __cplusplus < 201402L
BOOST_AUTO_TEST_CASE( test_main ) {}
#else
struct constexpr_char_traits
{
typedef char char_type;
typedef int int_type;
typedef std::streamoff off_type;
typedef std::streampos pos_type;
typedef std::mbstate_t state_type;
static void assign(char_type& c1, const char_type& c2) noexcept { c1 = c2; }
static constexpr bool eq(char_type c1, char_type c2) noexcept { return c1 == c2; }
static constexpr bool lt(char_type c1, char_type c2) noexcept { return c1 < c2; }
static constexpr int compare(const char_type* s1, const char_type* s2, size_t n) noexcept;
static constexpr size_t length(const char_type* s) noexcept;
static constexpr const char_type* find(const char_type* s, size_t n, const char_type& a) noexcept;
static constexpr char_type* move(char_type* s1, const char_type* s2, size_t n) noexcept;
static constexpr char_type* copy(char_type* s1, const char_type* s2, size_t n) noexcept;
static constexpr char_type* assign(char_type* s, size_t n, char_type a) noexcept;
static constexpr int_type not_eof(int_type c) noexcept { return eq_int_type(c, eof()) ? ~eof() : c; }
static constexpr char_type to_char_type(int_type c) noexcept { return char_type(c); }
static constexpr int_type to_int_type(char_type c) noexcept { return int_type(c); }
static constexpr bool eq_int_type(int_type c1, int_type c2) noexcept { return c1 == c2; }
static constexpr int_type eof() noexcept { return EOF; }
};
// yields:
// 0 if for each i in [0,n), X::eq(s1[i],s2[i]) is true;
// else, a negative value if, for some j in [0,n), X::lt(s1[j],s2[j]) is true and
// for each i in [0,j) X::eq(s2[i],s2[i]) is true;
// else a positive value.
constexpr int constexpr_char_traits::compare(const char_type* s1, const char_type* s2, size_t n) noexcept
{
for (; n != 0; --n, ++s1, ++s2)
{
if (lt(*s1, *s2))
return -1;
if (lt(*s2, *s1))
return 1;
}
return 0;
}
// yields: the smallest i such that X::eq(s[i],charT()) is true.
constexpr size_t constexpr_char_traits::length(const char_type* s) noexcept
{
size_t len = 0;
for (; !eq(*s, char_type(0)); ++s)
++len;
return len;
}
typedef boost::basic_string_view<char, constexpr_char_traits> string_view;
BOOST_AUTO_TEST_CASE( test_main )
{
constexpr string_view sv1;
constexpr string_view sv2{"abc", 3}; // ptr, len
constexpr string_view sv3{"def"}; // ptr
constexpr const char *s1 = "";
constexpr const char *s2 = "abc";
static_assert( (sv1 == sv1), "" );
static_assert(!(sv1 == sv2), "" );
static_assert( (sv1 != sv2), "" );
static_assert( (sv1 < sv2), "" );
static_assert( (sv1 <= sv2), "" );
static_assert(!(sv1 > sv2), "" );
static_assert(!(sv1 >= sv2), "" );
static_assert(!(s1 == sv2), "" );
static_assert( (s1 != sv2), "" );
static_assert( (s1 < sv2), "" );
static_assert( (s1 <= sv2), "" );
static_assert(!(s1 > sv2), "" );
static_assert(!(s1 >= sv2), "" );
static_assert(!(sv1 == s2), "" );
static_assert( (sv1 != s2), "" );
static_assert( (sv1 < s2), "" );
static_assert( (sv1 <= s2), "" );
static_assert(!(sv1 > s2), "" );
static_assert(!(sv1 >= s2), "" );
static_assert( sv1.compare(sv2) < 0, "" );
static_assert( sv1.compare(sv1) == 0, "" );
static_assert( sv3.compare(sv1) > 0, "" );
static_assert( sv1.compare(s2) < 0, "" );
static_assert( sv1.compare(s1) == 0, "" );
static_assert( sv3.compare(s1) > 0, "" );
}
#endif

View File

@ -0,0 +1,28 @@
/*
Copyright (c) Marshall Clow 2017.
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)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <algorithm>
#include <string>
#include <boost/utility/string_view.hpp>
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
#error "Unsupported test"
#endif
#include "boost/test/minimal.hpp"
std::string makeatemp() { return "abc"; }
int test_main(int, char **)
{
boost::basic_string_view<char> sv(makeatemp());
return 0;
}

109
test/string_view_test1.cpp Normal file
View File

@ -0,0 +1,109 @@
/*
Copyright (c) Marshall Clow 2012-2012.
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)
For more information, see http://www.boost.org
*/
#include <iostream>
#include <algorithm>
#include <string>
#include <boost/utility/string_view.hpp>
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
typedef boost::string_view string_view;
// Should be equal
void interop ( const std::string &str, string_view ref ) {
// BOOST_CHECK ( str == ref );
BOOST_CHECK ( str.size () == ref.size ());
BOOST_CHECK ( std::equal ( str.begin (), str.end (), ref.begin ()));
BOOST_CHECK ( std::equal ( str.rbegin (), str.rend (), ref.rbegin ()));
}
void null_tests ( const char *p ) {
// All zero-length string-refs should be equal
string_view sr1; // NULL, 0
string_view sr2 ( NULL, 0 );
string_view sr3 ( p, 0 );
string_view sr4 ( p );
sr4.clear ();
BOOST_CHECK ( sr1 == sr2 );
BOOST_CHECK ( sr1 == sr3 );
BOOST_CHECK ( sr2 == sr3 );
BOOST_CHECK ( sr1 == sr4 );
}
// make sure that substrings work just like strings
void test_substr ( const std::string &str ) {
const size_t sz = str.size ();
string_view ref ( str );
// Substrings at the end
for ( size_t i = 0; i <= sz; ++ i )
interop ( str.substr ( i ), ref.substr ( i ));
// Substrings at the beginning
for ( size_t i = 0; i <= sz; ++ i )
interop ( str.substr ( 0, i ), ref.substr ( 0, i ));
// All possible substrings
for ( size_t i = 0; i < sz; ++i )
for ( size_t j = i; j < sz; ++j )
interop ( str.substr ( i, j ), ref.substr ( i, j ));
}
// make sure that removing prefixes and suffixes work just like strings
void test_remove ( const std::string &str ) {
const size_t sz = str.size ();
std::string work;
string_view ref;
for ( size_t i = 1; i <= sz; ++i ) {
work = str;
ref = str;
while ( ref.size () >= i ) {
interop ( work, ref );
work.erase ( 0, i );
ref.remove_prefix (i);
}
}
for ( size_t i = 1; i < sz; ++ i ) {
work = str;
ref = str;
while ( ref.size () >= i ) {
interop ( work, ref );
work.erase ( work.size () - i, i );
ref.remove_suffix (i);
}
}
}
const char *test_strings [] = {
"",
"1",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
"0123456789",
NULL
};
BOOST_AUTO_TEST_CASE( test_main )
{
const char **p = &test_strings[0];
while ( *p != NULL ) {
interop ( *p, *p );
test_substr ( *p );
test_remove ( *p );
null_tests ( *p );
p++;
}
}

405
test/string_view_test2.cpp Normal file
View File

@ -0,0 +1,405 @@
/*
Copyright (c) Marshall Clow 2012-2012.
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)
For more information, see http://www.boost.org
*/
#include <new> // for placement new
#include <iostream>
#include <cstddef> // for NULL, std::size_t, std::ptrdiff_t
#include <cstring> // for std::strchr and std::strcmp
#include <cstdlib> // for std::malloc and std::free
#include <boost/utility/string_view.hpp>
#include <boost/config.hpp>
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
typedef boost::string_view string_view;
void ends_with ( const char *arg ) {
const size_t sz = std::strlen ( arg );
string_view sr ( arg );
string_view sr2 ( arg );
const char *p = arg;
while ( *p ) {
BOOST_CHECK ( sr.ends_with ( p ));
++p;
}
while ( !sr2.empty ()) {
BOOST_CHECK ( sr.ends_with ( sr2 ));
sr2.remove_prefix (1);
}
sr2 = arg;
while ( !sr2.empty ()) {
BOOST_CHECK ( sr.ends_with ( sr2 ));
sr2.remove_prefix (1);
}
char ch = sz == 0 ? '\0' : arg [ sz - 1 ];
sr2 = arg;
if ( sz > 0 )
BOOST_CHECK ( sr2.ends_with ( ch ));
BOOST_CHECK ( !sr2.ends_with ( ++ch ));
BOOST_CHECK ( sr2.ends_with ( string_view()));
}
void starts_with ( const char *arg ) {
const size_t sz = std::strlen ( arg );
string_view sr ( arg );
string_view sr2 ( arg );
const char *p = arg + std::strlen ( arg ) - 1;
while ( p >= arg ) {
std::string foo ( arg, p + 1 );
BOOST_CHECK ( sr.starts_with ( foo ));
--p;
}
while ( !sr2.empty ()) {
BOOST_CHECK ( sr.starts_with ( sr2 ));
sr2.remove_suffix (1);
}
char ch = *arg;
sr2 = arg;
if ( sz > 0 )
BOOST_CHECK ( sr2.starts_with ( ch ));
BOOST_CHECK ( !sr2.starts_with ( ++ch ));
BOOST_CHECK ( sr2.starts_with ( string_view ()));
}
void reverse ( const char *arg ) {
// Round trip
string_view sr1 ( arg );
std::string string1 ( sr1.rbegin (), sr1.rend ());
string_view sr2 ( string1 );
std::string string2 ( sr2.rbegin (), sr2.rend ());
BOOST_CHECK ( std::equal ( sr2.rbegin (), sr2.rend (), arg ));
BOOST_CHECK ( string2 == arg );
BOOST_CHECK ( std::equal ( sr1.begin (), sr1.end (), string2.begin ()));
}
// This helper function eliminates signed vs. unsigned warnings
string_view::size_type ptr_diff ( const char *res, const char *base ) {
BOOST_CHECK ( res >= base );
return static_cast<string_view::size_type> ( res - base );
}
void find ( const char *arg ) {
string_view sr1;
string_view sr2;
const char *p;
// Look for each character in the string(searching from the start)
p = arg;
sr1 = arg;
while ( *p ) {
string_view::size_type pos = sr1.find(*p);
BOOST_CHECK ( pos != string_view::npos && ( pos <= ptr_diff ( p, arg )));
++p;
}
// Look for each character in the string (searching from the end)
p = arg;
sr1 = arg;
while ( *p ) {
string_view::size_type pos = sr1.rfind(*p);
BOOST_CHECK ( pos != string_view::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg )));
++p;
}
// Look for pairs on characters (searching from the start)
sr1 = arg;
p = arg;
while ( *p && *(p+1)) {
string_view sr3 ( p, 2 );
string_view::size_type pos = sr1.find ( sr3 );
BOOST_CHECK ( pos != string_view::npos && pos <= static_cast<string_view::size_type>( p - arg ));
p++;
}
sr1 = arg;
p = arg;
// for all possible chars, see if we find them in the right place.
// Note that strchr will/might do the _wrong_ thing if we search for NULL
for ( int ch = 1; ch < 256; ++ch ) {
string_view::size_type pos = sr1.find(ch);
const char *strp = std::strchr ( arg, ch );
BOOST_CHECK (( strp == NULL ) == ( pos == string_view::npos ));
if ( strp != NULL )
BOOST_CHECK ( ptr_diff ( strp, arg ) == pos );
}
sr1 = arg;
p = arg;
// for all possible chars, see if we find them in the right place.
// Note that strchr will/might do the _wrong_ thing if we search for NULL
for ( int ch = 1; ch < 256; ++ch ) {
string_view::size_type pos = sr1.rfind(ch);
const char *strp = std::strrchr ( arg, ch );
BOOST_CHECK (( strp == NULL ) == ( pos == string_view::npos ));
if ( strp != NULL )
BOOST_CHECK ( ptr_diff ( strp, arg ) == pos );
}
// Find everything at the start
p = arg;
sr1 = arg;
while ( !sr1.empty ()) {
string_view::size_type pos = sr1.find(*p);
BOOST_CHECK ( pos == 0 );
sr1.remove_prefix (1);
++p;
}
// Find everything at the end
sr1 = arg;
p = arg + std::strlen ( arg ) - 1;
while ( !sr1.empty ()) {
string_view::size_type pos = sr1.rfind(*p);
BOOST_CHECK ( pos == sr1.size () - 1 );
sr1.remove_suffix (1);
--p;
}
// Find everything at the start
sr1 = arg;
p = arg;
while ( !sr1.empty ()) {
string_view::size_type pos = sr1.find_first_of(*p);
BOOST_CHECK ( pos == 0 );
sr1.remove_prefix (1);
++p;
}
// Find everything at the end
sr1 = arg;
p = arg + std::strlen ( arg ) - 1;
while ( !sr1.empty ()) {
string_view::size_type pos = sr1.find_last_of(*p);
BOOST_CHECK ( pos == sr1.size () - 1 );
sr1.remove_suffix (1);
--p;
}
// Basic sanity checking for "find_first_of / find_first_not_of"
sr1 = arg;
sr2 = arg;
while ( !sr1.empty() ) {
BOOST_CHECK ( sr1.find_first_of ( sr2 ) == 0 );
BOOST_CHECK ( sr1.find_first_not_of ( sr2 ) == string_view::npos );
sr1.remove_prefix ( 1 );
}
p = arg;
sr1 = arg;
while ( *p ) {
string_view::size_type pos1 = sr1.find_first_of(*p);
string_view::size_type pos2 = sr1.find_first_not_of(*p);
BOOST_CHECK ( pos1 != string_view::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg ));
if ( pos2 != string_view::npos ) {
for ( size_t i = 0 ; i < pos2; ++i )
BOOST_CHECK ( sr1[i] == *p );
BOOST_CHECK ( sr1 [ pos2 ] != *p );
}
BOOST_CHECK ( pos2 != pos1 );
++p;
}
// Basic sanity checking for "find_last_of / find_last_not_of"
sr1 = arg;
sr2 = arg;
while ( !sr1.empty() ) {
BOOST_CHECK ( sr1.find_last_of ( sr2 ) == ( sr1.size () - 1 ));
BOOST_CHECK ( sr1.find_last_not_of ( sr2 ) == string_view::npos );
sr1.remove_suffix ( 1 );
}
p = arg;
sr1 = arg;
while ( *p ) {
string_view::size_type pos1 = sr1.find_last_of(*p);
string_view::size_type pos2 = sr1.find_last_not_of(*p);
BOOST_CHECK ( pos1 != string_view::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg ));
BOOST_CHECK ( pos2 == string_view::npos || pos1 < sr1.size ());
if ( pos2 != string_view::npos ) {
for ( size_t i = sr1.size () -1 ; i > pos2; --i )
BOOST_CHECK ( sr1[i] == *p );
BOOST_CHECK ( sr1 [ pos2 ] != *p );
}
BOOST_CHECK ( pos2 != pos1 );
++p;
}
}
template <typename T>
class custom_allocator {
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef void* void_pointer;
typedef const void* const_void_pointer;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T& reference;
typedef const T& const_reference;
template<class U>
struct rebind {
typedef custom_allocator<U> other;
};
custom_allocator() BOOST_NOEXCEPT {}
template <typename U>
custom_allocator(custom_allocator<U> const&) BOOST_NOEXCEPT {}
pointer allocate(size_type n) const {
return static_cast<pointer>(std::malloc(sizeof(value_type) * n));
}
void deallocate(pointer p, size_type) const BOOST_NOEXCEPT {
std::free(p);
}
pointer address(reference value) const BOOST_NOEXCEPT {
return &value;
}
const_pointer address(const_reference value) const BOOST_NOEXCEPT {
return &value;
}
BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT {
return (~(size_type)0u) / sizeof(value_type);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class U, class... Args>
void construct(U* ptr, Args&&... args) const {
::new((void*)ptr) U(static_cast<Args&&>(args)...);
}
#else
template <class U, class V>
void construct(U* ptr, V&& value) const {
::new((void*)ptr) U(static_cast<V&&>(value));
}
#endif
#else
template <class U, class V>
void construct(U* ptr, const V& value) const {
::new((void*)ptr) U(value);
}
#endif
template <class U>
void construct(U* ptr) const {
::new((void*)ptr) U();
}
template <class U>
void destroy(U* ptr) const {
(void)ptr;
ptr->~U();
}
};
template <typename T, typename U>
BOOST_CONSTEXPR bool operator==(const custom_allocator<T> &, const custom_allocator<U> &) BOOST_NOEXCEPT {
return true;
}
template <typename T, typename U>
BOOST_CONSTEXPR bool operator!=(const custom_allocator<T> &, const custom_allocator<U> &) BOOST_NOEXCEPT {
return false;
}
void to_string ( const char *arg ) {
string_view sr1;
std::string str1;
std::string str2;
str1.assign ( arg );
sr1 = arg;
// str2 = sr1.to_string<std::allocator<char> > ();
str2 = sr1.to_string ();
BOOST_CHECK ( str1 == str2 );
std::basic_string<char, std::char_traits<char>, custom_allocator<char> > str3 = sr1.to_string(custom_allocator<char>());
BOOST_CHECK ( std::strcmp(str1.c_str(), str3.c_str()) == 0 );
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
std::string str4 = static_cast<std::string> ( sr1 );
BOOST_CHECK ( str1 == str4 );
#endif
}
void compare ( const char *arg ) {
string_view sr1;
std::string str1;
std::string str2 = str1;
str1.assign ( arg );
sr1 = arg;
BOOST_CHECK ( sr1 == sr1); // compare string_view and string_view
BOOST_CHECK ( sr1 == str1); // compare string and string_view
BOOST_CHECK ( str1 == sr1 ); // compare string_view and string
BOOST_CHECK ( sr1 == arg ); // compare string_view and pointer
BOOST_CHECK ( arg == sr1 ); // compare pointer and string_view
if ( sr1.size () > 0 ) {
(*str1.rbegin())++;
BOOST_CHECK ( sr1 != str1 );
BOOST_CHECK ( str1 != sr1 );
BOOST_CHECK ( sr1 < str1 );
BOOST_CHECK ( sr1 <= str1 );
BOOST_CHECK ( str1 > sr1 );
BOOST_CHECK ( str1 >= sr1 );
(*str1.rbegin()) -= 2;
BOOST_CHECK ( sr1 != str1 );
BOOST_CHECK ( str1 != sr1 );
BOOST_CHECK ( sr1 > str1 );
BOOST_CHECK ( sr1 >= str1 );
BOOST_CHECK ( str1 < sr1 );
BOOST_CHECK ( str1 <= sr1 );
}
}
const char *test_strings [] = {
"",
"0",
"abc",
"AAA", // all the same
"adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf",
"abc\0asdfadsfasf",
NULL
};
BOOST_AUTO_TEST_CASE( test_main )
{
const char **p = &test_strings[0];
while ( *p != NULL ) {
starts_with ( *p );
ends_with ( *p );
reverse ( *p );
find ( *p );
to_string ( *p );
compare ( *p );
p++;
}
}

View File

@ -0,0 +1,179 @@
/*
* Copyright Andrey Semashev 2013.
* 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)
*/
/*!
* \file string_ref_test_io.cpp
* \author Andrey Semashev
* \date 26.05.2013
*
* \brief This header contains tests for stream operations of \c basic_string_ref.
*/
#define BOOST_TEST_MODULE string_ref_test_io
#include <boost/utility/string_view.hpp>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <string>
#include <boost/config.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/test/unit_test.hpp>
typedef boost::mpl::vector<
char
#if !defined(BOOST_NO_STD_WSTRING) && !defined(BOOST_NO_STD_WSTREAMBUF) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
, wchar_t
#endif
/* Current implementations seem to be missing codecvt facets to convert chars to char16_t and char32_t even though the types are available.
#if !defined(BOOST_NO_CXX11_CHAR16_T)
, char16_t
#endif
#if !defined(BOOST_NO_CXX11_CHAR32_T)
, char32_t
#endif
*/
>::type char_types;
static const char* test_strings[] =
{
"begin",
"abcd",
"end"
};
//! The context with test data for particular character type
template< typename CharT >
struct context
{
typedef CharT char_type;
typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type;
string_type begin, abcd, end;
context()
{
boost::string_view str = test_strings[0];
std::copy(str.begin(), str.end(), std::back_inserter(begin));
str = test_strings[1];
std::copy(str.begin(), str.end(), std::back_inserter(abcd));
str = test_strings[2];
std::copy(str.begin(), str.end(), std::back_inserter(end));
}
};
// Test regular output
BOOST_AUTO_TEST_CASE_TEMPLATE(string_view_output, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_view< char_type > string_view_type;
context< char_type > ctx;
ostream_type strm;
strm << string_view_type(ctx.abcd);
BOOST_CHECK(strm.str() == ctx.abcd);
}
// Test support for padding
BOOST_AUTO_TEST_CASE_TEMPLATE(padding, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_view< char_type > string_view_type;
context< char_type > ctx;
// Test for padding
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::setw(8) << string_view_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
// Test for long padding
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::setw(100) << string_view_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
// Test that short width does not truncate the string
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::setw(1) << string_view_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
}
// Test support for padding fill
BOOST_AUTO_TEST_CASE_TEMPLATE(padding_fill, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_view< char_type > string_view_type;
context< char_type > ctx;
ostream_type strm_ref;
strm_ref << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_view_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
// Test support for alignment
BOOST_AUTO_TEST_CASE_TEMPLATE(alignment, CharT, char_types)
{
typedef CharT char_type;
typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_view< char_type > string_view_type;
context< char_type > ctx;
// Left alignment
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::left << std::setw(8) << string_view_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
// Right alignment
{
ostream_type strm_ref;
strm_ref << ctx.begin << std::right << std::setw(8) << string_view_type(ctx.abcd) << ctx.end;
ostream_type strm_correct;
strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str());
}
}

View File

@ -132,7 +132,7 @@ int main()
const unsigned num_failures =
FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<derived_struct>()) +
FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<virtual_destructor_holder[2]>()) +
FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<private_int_array_pair>());
FAILED_TO_VALUE_INITIALIZE(boost::value_initialized<private_int_array_pair>());
#ifdef BOOST_DETAIL_VALUE_INIT_WORKAROUND_SUGGESTED
// One or more failures are expected.