mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-26 06:15:16 +00:00
376aaac146
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@13298 a592a061-630c-0410-9148-cb99ea01b6c8
1057 lines
33 KiB
C++
1057 lines
33 KiB
C++
//
|
|
// (C) Copyright Jeremy Siek 2000.
|
|
// 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)
|
|
//
|
|
// Revision History:
|
|
// 05 May 2001: Workarounds for HP aCC from Thomas Matelich. (Jeremy Siek)
|
|
// 02 April 2001: Removed limits header altogether. (Jeremy Siek)
|
|
// 01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock)
|
|
//
|
|
|
|
// See http://www.boost.org/libs/concept_check for documentation.
|
|
|
|
#ifndef BOOST_CONCEPT_CHECKS_HPP
|
|
#define BOOST_CONCEPT_CHECKS_HPP
|
|
|
|
#include <boost/config.hpp>
|
|
#include <boost/iterator.hpp>
|
|
#include <boost/type_traits/conversion_traits.hpp>
|
|
#include <utility>
|
|
#include <boost/type_traits/conversion_traits.hpp>
|
|
#include <boost/static_assert.hpp>
|
|
#include <boost/mpl/identity.hpp>
|
|
|
|
|
|
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__BORLANDC__)
|
|
#define BOOST_FPTR
|
|
#else
|
|
#define BOOST_FPTR &
|
|
#endif
|
|
|
|
namespace boost {
|
|
|
|
/*
|
|
"inline" is used for ignore_unused_variable_warning()
|
|
and function_requires() to make sure there is no
|
|
overhead with g++.
|
|
*/
|
|
|
|
template <class T> inline void ignore_unused_variable_warning(const T&) { }
|
|
|
|
// the unused, defaulted parameter is a workaround for MSVC and Compaq C++
|
|
template <class Concept>
|
|
inline void function_requires(mpl::identity<Concept>* = 0)
|
|
{
|
|
#if !defined(NDEBUG)
|
|
void (Concept::*x)() = BOOST_FPTR Concept::constraints;
|
|
ignore_unused_variable_warning(x);
|
|
#endif
|
|
}
|
|
|
|
#define BOOST_CLASS_REQUIRE(type_var, ns, concept) \
|
|
typedef void (ns::concept <type_var>::* func##type_var##concept)(); \
|
|
template <func##type_var##concept Tp1_> \
|
|
struct concept_checking_##type_var##concept { }; \
|
|
typedef concept_checking_##type_var##concept< \
|
|
BOOST_FPTR ns::concept<type_var>::constraints> \
|
|
concept_checking_typedef_##type_var##concept
|
|
|
|
#define BOOST_CLASS_REQUIRE2(type_var1, type_var2, ns, concept) \
|
|
typedef void (ns::concept <type_var1,type_var2>::* \
|
|
func##type_var1##type_var2##concept)(); \
|
|
template <func##type_var1##type_var2##concept Tp1_> \
|
|
struct concept_checking_##type_var1##type_var2##concept { }; \
|
|
typedef concept_checking_##type_var1##type_var2##concept< \
|
|
BOOST_FPTR ns::concept<type_var1,type_var2>::constraints> \
|
|
concept_checking_typedef_##type_var1##type_var2##concept
|
|
|
|
#define BOOST_CLASS_REQUIRE3(tv1, tv2, tv3, ns, concept) \
|
|
typedef void (ns::concept <tv1,tv2,tv3>::* \
|
|
func##tv1##tv2##tv3##concept)(); \
|
|
template <func##tv1##tv2##tv3##concept Tp1_> \
|
|
struct concept_checking_##tv1##tv2##tv3##concept { }; \
|
|
typedef concept_checking_##tv1##tv2##tv3##concept< \
|
|
BOOST_FPTR ns::concept<tv1,tv2,tv3>::constraints> \
|
|
concept_checking_typedef_##tv1##tv2##tv3##concept
|
|
|
|
#define BOOST_CLASS_REQUIRE4(tv1, tv2, tv3, tv4, ns, concept) \
|
|
typedef void (ns::concept <tv1,tv2,tv3,tv4>::* \
|
|
func##tv1##tv2##tv3##tv4##concept)(); \
|
|
template <func##tv1##tv2##tv3##tv4##concept Tp1_> \
|
|
struct concept_checking_##tv1##tv2##tv3##tv4##concept { }; \
|
|
typedef concept_checking_##tv1##tv2##tv3##tv4##concept< \
|
|
BOOST_FPTR ns::concept<tv1,tv2,tv3,tv4>::constraints> \
|
|
concept_checking_typedef_##tv1##tv2##tv3##tv4##concept
|
|
|
|
// NOTE: The BOOST_CLASS_REQUIRES (with an 'S' at the end) is deprecated.
|
|
|
|
// The BOOST_CLASS_REQUIRES macros use function pointers as
|
|
// template parameters, which VC++ does not support.
|
|
|
|
#if defined(BOOST_NO_FUNCTION_PTR_TEMPLATE_PARAMETERS)
|
|
|
|
#define BOOST_CLASS_REQUIRES(type_var, concept)
|
|
#define BOOST_CLASS_REQUIRES2(type_var1, type_var2, concept)
|
|
#define BOOST_CLASS_REQUIRES3(type_var1, type_var2, type_var3, concept)
|
|
#define BOOST_CLASS_REQUIRES4(type_var1, type_var2, type_var3, type_var4, concept)
|
|
|
|
#else
|
|
|
|
#define BOOST_CLASS_REQUIRES(type_var, concept) \
|
|
typedef void (concept <type_var>::* func##type_var##concept)(); \
|
|
template <func##type_var##concept Tp1_> \
|
|
struct concept_checking_##type_var##concept { }; \
|
|
typedef concept_checking_##type_var##concept< \
|
|
BOOST_FPTR concept <type_var>::constraints> \
|
|
concept_checking_typedef_##type_var##concept
|
|
|
|
#define BOOST_CLASS_REQUIRES2(type_var1, type_var2, concept) \
|
|
typedef void (concept <type_var1,type_var2>::* func##type_var1##type_var2##concept)(); \
|
|
template <func##type_var1##type_var2##concept Tp1_> \
|
|
struct concept_checking_##type_var1##type_var2##concept { }; \
|
|
typedef concept_checking_##type_var1##type_var2##concept< \
|
|
BOOST_FPTR concept <type_var1,type_var2>::constraints> \
|
|
concept_checking_typedef_##type_var1##type_var2##concept
|
|
|
|
#define BOOST_CLASS_REQUIRES3(type_var1, type_var2, type_var3, concept) \
|
|
typedef void (concept <type_var1,type_var2,type_var3>::* func##type_var1##type_var2##type_var3##concept)(); \
|
|
template <func##type_var1##type_var2##type_var3##concept Tp1_> \
|
|
struct concept_checking_##type_var1##type_var2##type_var3##concept { }; \
|
|
typedef concept_checking_##type_var1##type_var2##type_var3##concept< \
|
|
BOOST_FPTR concept <type_var1,type_var2,type_var3>::constraints> \
|
|
concept_checking_typedef_##type_var1##type_var2##type_var3##concept
|
|
|
|
#define BOOST_CLASS_REQUIRES4(type_var1, type_var2, type_var3, type_var4, concept) \
|
|
typedef void (concept <type_var1,type_var2,type_var3,type_var4>::* func##type_var1##type_var2##type_var3##type_var4##concept)(); \
|
|
template <func##type_var1##type_var2##type_var3##type_var4##concept Tp1_> \
|
|
struct concept_checking_##type_var1##type_var2##type_var3##type_var4##concept { }; \
|
|
typedef concept_checking_##type_var1##type_var2##type_var3##type_var4##concept< \
|
|
BOOST_FPTR concept <type_var1,type_var2,type_var3,type_var4>::constraints> \
|
|
concept_checking_typedef_##type_var1##type_var2##type_var3##type_var4##concept
|
|
|
|
|
|
#endif
|
|
|
|
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
template <class T, class U>
|
|
struct require_same { };
|
|
|
|
template <class T>
|
|
struct require_same<T,T> { typedef T type; };
|
|
#else
|
|
// This version does not perform checking, but will not do any harm.
|
|
template <class T, class U>
|
|
struct require_same { typedef T type; };
|
|
#endif
|
|
|
|
template <class T>
|
|
struct IntegerConcept {
|
|
void constraints() {
|
|
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
x.error_type_must_be_an_integer_type();
|
|
#endif
|
|
}
|
|
T x;
|
|
};
|
|
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
template <> struct IntegerConcept<short> { void constraints() {} };
|
|
template <> struct IntegerConcept<unsigned short> { void constraints() {} };
|
|
template <> struct IntegerConcept<int> { void constraints() {} };
|
|
template <> struct IntegerConcept<unsigned int> { void constraints() {} };
|
|
template <> struct IntegerConcept<long> { void constraints() {} };
|
|
template <> struct IntegerConcept<unsigned long> { void constraints() {} };
|
|
// etc.
|
|
#endif
|
|
|
|
template <class T>
|
|
struct SignedIntegerConcept {
|
|
void constraints() {
|
|
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
x.error_type_must_be_a_signed_integer_type();
|
|
#endif
|
|
}
|
|
T x;
|
|
};
|
|
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
template <> struct SignedIntegerConcept<short> { void constraints() {} };
|
|
template <> struct SignedIntegerConcept<int> { void constraints() {} };
|
|
template <> struct SignedIntegerConcept<long> { void constraints() {} };
|
|
# if defined(BOOST_HAS_LONG_LONG)
|
|
template <> struct SignedIntegerConcept< ::boost::long_long_type> { void constraints() {} };
|
|
# endif
|
|
// etc.
|
|
#endif
|
|
|
|
template <class T>
|
|
struct UnsignedIntegerConcept {
|
|
void constraints() {
|
|
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
x.error_type_must_be_an_unsigned_integer_type();
|
|
#endif
|
|
}
|
|
T x;
|
|
};
|
|
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
template <> struct UnsignedIntegerConcept<unsigned short>
|
|
{ void constraints() {} };
|
|
template <> struct UnsignedIntegerConcept<unsigned int>
|
|
{ void constraints() {} };
|
|
template <> struct UnsignedIntegerConcept<unsigned long>
|
|
{ void constraints() {} };
|
|
// etc.
|
|
#endif
|
|
|
|
//===========================================================================
|
|
// Basic Concepts
|
|
|
|
template <class TT>
|
|
struct DefaultConstructibleConcept
|
|
{
|
|
void constraints() {
|
|
TT a; // require default constructor
|
|
ignore_unused_variable_warning(a);
|
|
}
|
|
};
|
|
|
|
template <class TT>
|
|
struct AssignableConcept
|
|
{
|
|
void constraints() {
|
|
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
|
|
a = a; // require assignment operator
|
|
#endif
|
|
const_constraints(a);
|
|
}
|
|
void const_constraints(const TT& b) {
|
|
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
|
|
a = b; // const required for argument to assignment
|
|
#endif
|
|
}
|
|
TT a;
|
|
};
|
|
|
|
template <class TT>
|
|
struct CopyConstructibleConcept
|
|
{
|
|
void constraints() {
|
|
TT a(b); // require copy constructor
|
|
TT* ptr = &a; // require address of operator
|
|
const_constraints(a);
|
|
ignore_unused_variable_warning(ptr);
|
|
}
|
|
void const_constraints(const TT& a) {
|
|
TT c(a); // require const copy constructor
|
|
const TT* ptr = &a; // require const address of operator
|
|
ignore_unused_variable_warning(c);
|
|
ignore_unused_variable_warning(ptr);
|
|
}
|
|
TT b;
|
|
};
|
|
|
|
// The SGI STL version of Assignable requires copy constructor and operator=
|
|
template <class TT>
|
|
struct SGIAssignableConcept
|
|
{
|
|
void constraints() {
|
|
TT b(a);
|
|
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
|
|
a = a; // require assignment operator
|
|
#endif
|
|
const_constraints(a);
|
|
ignore_unused_variable_warning(b);
|
|
}
|
|
void const_constraints(const TT& b) {
|
|
TT c(b);
|
|
#if !defined(_ITERATOR_) // back_insert_iterator broken for VC++ STL
|
|
a = b; // const required for argument to assignment
|
|
#endif
|
|
ignore_unused_variable_warning(c);
|
|
}
|
|
TT a;
|
|
};
|
|
|
|
template <class X, class Y>
|
|
struct ConvertibleConcept
|
|
{
|
|
void constraints() {
|
|
Y y = x;
|
|
ignore_unused_variable_warning(y);
|
|
}
|
|
X x;
|
|
};
|
|
|
|
// The C++ standard requirements for many concepts talk about return
|
|
// types that must be "convertible to bool". The problem with this
|
|
// requirement is that it leaves the door open for evil proxies that
|
|
// define things like operator|| with strange return types. Two
|
|
// possible solutions are:
|
|
// 1) require the return type to be exactly bool
|
|
// 2) stay with convertible to bool, and also
|
|
// specify stuff about all the logical operators.
|
|
// For now we just test for convertible to bool.
|
|
template <class TT>
|
|
void require_boolean_expr(const TT& t) {
|
|
bool x = t;
|
|
ignore_unused_variable_warning(x);
|
|
}
|
|
|
|
template <class TT>
|
|
struct EqualityComparableConcept
|
|
{
|
|
void constraints() {
|
|
require_boolean_expr(a == b);
|
|
require_boolean_expr(a != b);
|
|
}
|
|
TT a, b;
|
|
};
|
|
|
|
template <class TT>
|
|
struct LessThanComparableConcept
|
|
{
|
|
void constraints() {
|
|
require_boolean_expr(a < b);
|
|
}
|
|
TT a, b;
|
|
};
|
|
|
|
// This is equivalent to SGI STL's LessThanComparable.
|
|
template <class TT>
|
|
struct ComparableConcept
|
|
{
|
|
void constraints() {
|
|
require_boolean_expr(a < b);
|
|
require_boolean_expr(a > b);
|
|
require_boolean_expr(a <= b);
|
|
require_boolean_expr(a >= b);
|
|
}
|
|
TT a, b;
|
|
};
|
|
|
|
#define BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(OP,NAME) \
|
|
template <class First, class Second> \
|
|
struct NAME { \
|
|
void constraints() { (void)constraints_(); } \
|
|
bool constraints_() { \
|
|
return a OP b; \
|
|
} \
|
|
First a; \
|
|
Second b; \
|
|
}
|
|
|
|
#define BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(OP,NAME) \
|
|
template <class Ret, class First, class Second> \
|
|
struct NAME { \
|
|
void constraints() { (void)constraints_(); } \
|
|
Ret constraints_() { \
|
|
return a OP b; \
|
|
} \
|
|
First a; \
|
|
Second b; \
|
|
}
|
|
|
|
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, EqualOpConcept);
|
|
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, NotEqualOpConcept);
|
|
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, LessThanOpConcept);
|
|
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, LessEqualOpConcept);
|
|
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, GreaterThanOpConcept);
|
|
BOOST_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, GreaterEqualOpConcept);
|
|
|
|
BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, PlusOpConcept);
|
|
BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, TimesOpConcept);
|
|
BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, DivideOpConcept);
|
|
BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, SubtractOpConcept);
|
|
BOOST_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, ModOpConcept);
|
|
|
|
//===========================================================================
|
|
// Function Object Concepts
|
|
|
|
template <class Func, class Return>
|
|
struct GeneratorConcept
|
|
{
|
|
void constraints() {
|
|
const Return& r = f(); // require operator() member function
|
|
ignore_unused_variable_warning(r);
|
|
}
|
|
Func f;
|
|
};
|
|
|
|
|
|
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
template <class Func>
|
|
struct GeneratorConcept<Func,void>
|
|
{
|
|
void constraints() {
|
|
f(); // require operator() member function
|
|
}
|
|
Func f;
|
|
};
|
|
#endif
|
|
|
|
template <class Func, class Return, class Arg>
|
|
struct UnaryFunctionConcept
|
|
{
|
|
// required in case any of our template args are const-qualified:
|
|
UnaryFunctionConcept();
|
|
|
|
void constraints() {
|
|
r = f(arg); // require operator()
|
|
}
|
|
Func f;
|
|
Arg arg;
|
|
Return r;
|
|
};
|
|
|
|
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
template <class Func, class Arg>
|
|
struct UnaryFunctionConcept<Func, void, Arg> {
|
|
void constraints() {
|
|
f(arg); // require operator()
|
|
}
|
|
Func f;
|
|
Arg arg;
|
|
};
|
|
#endif
|
|
|
|
template <class Func, class Return, class First, class Second>
|
|
struct BinaryFunctionConcept
|
|
{
|
|
void constraints() {
|
|
r = f(first, second); // require operator()
|
|
}
|
|
Func f;
|
|
First first;
|
|
Second second;
|
|
Return r;
|
|
};
|
|
|
|
#if !defined BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
template <class Func, class First, class Second>
|
|
struct BinaryFunctionConcept<Func, void, First, Second>
|
|
{
|
|
void constraints() {
|
|
f(first, second); // require operator()
|
|
}
|
|
Func f;
|
|
First first;
|
|
Second second;
|
|
};
|
|
#endif
|
|
|
|
template <class Func, class Arg>
|
|
struct UnaryPredicateConcept
|
|
{
|
|
void constraints() {
|
|
require_boolean_expr(f(arg)); // require operator() returning bool
|
|
}
|
|
Func f;
|
|
Arg arg;
|
|
};
|
|
|
|
template <class Func, class First, class Second>
|
|
struct BinaryPredicateConcept
|
|
{
|
|
void constraints() {
|
|
require_boolean_expr(f(a, b)); // require operator() returning bool
|
|
}
|
|
Func f;
|
|
First a;
|
|
Second b;
|
|
};
|
|
|
|
// use this when functor is used inside a container class like std::set
|
|
template <class Func, class First, class Second>
|
|
struct Const_BinaryPredicateConcept {
|
|
void constraints() {
|
|
const_constraints(f);
|
|
}
|
|
void const_constraints(const Func& fun) {
|
|
function_requires<BinaryPredicateConcept<Func, First, Second> >();
|
|
// operator() must be a const member function
|
|
require_boolean_expr(fun(a, b));
|
|
}
|
|
Func f;
|
|
First a;
|
|
Second b;
|
|
};
|
|
|
|
template <class Func, class Return>
|
|
struct AdaptableGeneratorConcept
|
|
{
|
|
void constraints() {
|
|
typedef typename Func::result_type result_type;
|
|
BOOST_STATIC_ASSERT((is_convertible<result_type, Return>::value));
|
|
function_requires< GeneratorConcept<Func, result_type> >();
|
|
}
|
|
};
|
|
|
|
template <class Func, class Return, class Arg>
|
|
struct AdaptableUnaryFunctionConcept
|
|
{
|
|
void constraints() {
|
|
typedef typename Func::argument_type argument_type;
|
|
typedef typename Func::result_type result_type;
|
|
BOOST_STATIC_ASSERT((is_convertible<result_type, Return>::value));
|
|
BOOST_STATIC_ASSERT((is_convertible<Arg, argument_type>::value));
|
|
function_requires< UnaryFunctionConcept<Func, result_type, argument_type> >();
|
|
}
|
|
};
|
|
|
|
template <class Func, class Return, class First, class Second>
|
|
struct AdaptableBinaryFunctionConcept
|
|
{
|
|
void constraints() {
|
|
typedef typename Func::first_argument_type first_argument_type;
|
|
typedef typename Func::second_argument_type second_argument_type;
|
|
typedef typename Func::result_type result_type;
|
|
BOOST_STATIC_ASSERT((is_convertible<result_type, Return>::value));
|
|
BOOST_STATIC_ASSERT((is_convertible<First, first_argument_type>::value));
|
|
BOOST_STATIC_ASSERT((is_convertible<Second, second_argument_type>::value));
|
|
function_requires< BinaryFunctionConcept<Func, result_type,
|
|
first_argument_type, second_argument_type> >();
|
|
}
|
|
};
|
|
|
|
template <class Func, class Arg>
|
|
struct AdaptablePredicateConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< UnaryPredicateConcept<Func, Arg> >();
|
|
function_requires< AdaptableUnaryFunctionConcept<Func, bool, Arg> >();
|
|
}
|
|
};
|
|
|
|
template <class Func, class First, class Second>
|
|
struct AdaptableBinaryPredicateConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< BinaryPredicateConcept<Func, First, Second> >();
|
|
function_requires< AdaptableBinaryFunctionConcept<Func, bool, First, Second> >();
|
|
}
|
|
};
|
|
|
|
//===========================================================================
|
|
// Iterator Concepts
|
|
|
|
template <class TT>
|
|
struct InputIteratorConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< AssignableConcept<TT> >();
|
|
function_requires< EqualityComparableConcept<TT> >();
|
|
TT j(i);
|
|
(void)*i; // require dereference operator
|
|
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
// require iterator_traits typedef's
|
|
typedef typename std::iterator_traits<TT>::difference_type D;
|
|
// Hmm, the following is a bit fragile
|
|
//function_requires< SignedIntegerConcept<D> >();
|
|
typedef typename std::iterator_traits<TT>::reference R;
|
|
typedef typename std::iterator_traits<TT>::pointer P;
|
|
typedef typename std::iterator_traits<TT>::iterator_category C;
|
|
function_requires< ConvertibleConcept<C, std::input_iterator_tag> >();
|
|
#endif
|
|
++j; // require preincrement operator
|
|
i++; // require postincrement operator
|
|
}
|
|
TT i;
|
|
};
|
|
|
|
template <class TT, class ValueT>
|
|
struct OutputIteratorConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< AssignableConcept<TT> >();
|
|
++i; // require preincrement operator
|
|
i++; // require postincrement operator
|
|
*i++ = t; // require postincrement and assignment
|
|
}
|
|
TT i, j;
|
|
ValueT t;
|
|
};
|
|
|
|
template <class TT>
|
|
struct ForwardIteratorConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< InputIteratorConcept<TT> >();
|
|
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
typedef typename std::iterator_traits<TT>::iterator_category C;
|
|
function_requires< ConvertibleConcept<C, std::forward_iterator_tag> >();
|
|
typedef typename std::iterator_traits<TT>::reference reference;
|
|
reference r = *i;
|
|
ignore_unused_variable_warning(r);
|
|
#endif
|
|
}
|
|
TT i;
|
|
};
|
|
|
|
template <class TT>
|
|
struct Mutable_ForwardIteratorConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< ForwardIteratorConcept<TT> >();
|
|
*i++ = *i; // require postincrement and assignment
|
|
}
|
|
TT i;
|
|
};
|
|
|
|
template <class TT>
|
|
struct BidirectionalIteratorConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< ForwardIteratorConcept<TT> >();
|
|
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
typedef typename std::iterator_traits<TT>::iterator_category C;
|
|
function_requires< ConvertibleConcept<C,
|
|
std::bidirectional_iterator_tag> >();
|
|
#endif
|
|
--i; // require predecrement operator
|
|
i--; // require postdecrement operator
|
|
}
|
|
TT i;
|
|
};
|
|
|
|
template <class TT>
|
|
struct Mutable_BidirectionalIteratorConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< BidirectionalIteratorConcept<TT> >();
|
|
function_requires< Mutable_ForwardIteratorConcept<TT> >();
|
|
*i-- = *i; // require postdecrement and assignment
|
|
}
|
|
TT i;
|
|
};
|
|
|
|
|
|
template <class TT>
|
|
struct RandomAccessIteratorConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< BidirectionalIteratorConcept<TT> >();
|
|
function_requires< ComparableConcept<TT> >();
|
|
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
typedef typename std::iterator_traits<TT>::iterator_category C;
|
|
function_requires< ConvertibleConcept< C,
|
|
std::random_access_iterator_tag> >();
|
|
typedef typename std::iterator_traits<TT>::reference R;
|
|
#endif
|
|
|
|
i += n; // require assignment addition operator
|
|
i = i + n; i = n + i; // require addition with difference type
|
|
i -= n; // require assignment subtraction operator
|
|
i = i - n; // require subtraction with difference type
|
|
n = i - j; // require difference operator
|
|
(void)i[n]; // require element access operator
|
|
}
|
|
TT a, b;
|
|
TT i, j;
|
|
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
typename std::iterator_traits<TT>::difference_type n;
|
|
#else
|
|
std::ptrdiff_t n;
|
|
#endif
|
|
};
|
|
|
|
template <class TT>
|
|
struct Mutable_RandomAccessIteratorConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< RandomAccessIteratorConcept<TT> >();
|
|
function_requires< Mutable_BidirectionalIteratorConcept<TT> >();
|
|
i[n] = *i; // require element access and assignment
|
|
}
|
|
TT i;
|
|
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
|
typename std::iterator_traits<TT>::difference_type n;
|
|
#else
|
|
std::ptrdiff_t n;
|
|
#endif
|
|
};
|
|
|
|
//===========================================================================
|
|
// Container Concepts
|
|
|
|
template <class Container>
|
|
struct ContainerConcept
|
|
{
|
|
typedef typename Container::value_type value_type;
|
|
typedef typename Container::difference_type difference_type;
|
|
typedef typename Container::size_type size_type;
|
|
typedef typename Container::const_reference const_reference;
|
|
typedef typename Container::const_pointer const_pointer;
|
|
typedef typename Container::const_iterator const_iterator;
|
|
|
|
void constraints() {
|
|
function_requires< InputIteratorConcept<const_iterator> >();
|
|
function_requires< AssignableConcept<Container> >();
|
|
const_constraints(c);
|
|
}
|
|
void const_constraints(const Container& cc) {
|
|
i = cc.begin();
|
|
i = cc.end();
|
|
n = cc.size();
|
|
n = cc.max_size();
|
|
b = cc.empty();
|
|
}
|
|
Container c;
|
|
bool b;
|
|
const_iterator i;
|
|
size_type n;
|
|
};
|
|
|
|
template <class Container>
|
|
struct Mutable_ContainerConcept
|
|
{
|
|
typedef typename Container::value_type value_type;
|
|
typedef typename Container::reference reference;
|
|
typedef typename Container::iterator iterator;
|
|
typedef typename Container::pointer pointer;
|
|
|
|
void constraints() {
|
|
function_requires< ContainerConcept<Container> >();
|
|
function_requires< AssignableConcept<value_type> >();
|
|
function_requires< InputIteratorConcept<iterator> >();
|
|
|
|
i = c.begin();
|
|
i = c.end();
|
|
c.swap(c2);
|
|
}
|
|
iterator i;
|
|
Container c, c2;
|
|
};
|
|
|
|
template <class ForwardContainer>
|
|
struct ForwardContainerConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< ContainerConcept<ForwardContainer> >();
|
|
typedef typename ForwardContainer::const_iterator const_iterator;
|
|
function_requires< ForwardIteratorConcept<const_iterator> >();
|
|
}
|
|
};
|
|
|
|
template <class ForwardContainer>
|
|
struct Mutable_ForwardContainerConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< ForwardContainerConcept<ForwardContainer> >();
|
|
function_requires< Mutable_ContainerConcept<ForwardContainer> >();
|
|
typedef typename ForwardContainer::iterator iterator;
|
|
function_requires< Mutable_ForwardIteratorConcept<iterator> >();
|
|
}
|
|
};
|
|
|
|
template <class ReversibleContainer>
|
|
struct ReversibleContainerConcept
|
|
{
|
|
typedef typename ReversibleContainer::const_iterator const_iterator;
|
|
typedef typename ReversibleContainer::const_reverse_iterator
|
|
const_reverse_iterator;
|
|
|
|
void constraints() {
|
|
function_requires< ForwardContainerConcept<ReversibleContainer> >();
|
|
function_requires< BidirectionalIteratorConcept<const_iterator> >();
|
|
function_requires<
|
|
BidirectionalIteratorConcept<const_reverse_iterator> >();
|
|
const_constraints(c);
|
|
}
|
|
void const_constraints(const ReversibleContainer& cc) {
|
|
const_reverse_iterator i = cc.rbegin();
|
|
i = cc.rend();
|
|
}
|
|
ReversibleContainer c;
|
|
};
|
|
|
|
template <class ReversibleContainer>
|
|
struct Mutable_ReversibleContainerConcept
|
|
{
|
|
typedef typename ReversibleContainer::iterator iterator;
|
|
typedef typename ReversibleContainer::reverse_iterator reverse_iterator;
|
|
|
|
void constraints() {
|
|
function_requires< ReversibleContainerConcept<ReversibleContainer> >();
|
|
function_requires<
|
|
Mutable_ForwardContainerConcept<ReversibleContainer> >();
|
|
function_requires< Mutable_BidirectionalIteratorConcept<iterator> >();
|
|
function_requires<
|
|
Mutable_BidirectionalIteratorConcept<reverse_iterator> >();
|
|
|
|
reverse_iterator i = c.rbegin();
|
|
i = c.rend();
|
|
}
|
|
ReversibleContainer c;
|
|
};
|
|
|
|
template <class RandomAccessContainer>
|
|
struct RandomAccessContainerConcept
|
|
{
|
|
typedef typename RandomAccessContainer::size_type size_type;
|
|
typedef typename RandomAccessContainer::const_reference const_reference;
|
|
typedef typename RandomAccessContainer::const_iterator const_iterator;
|
|
typedef typename RandomAccessContainer::const_reverse_iterator
|
|
const_reverse_iterator;
|
|
|
|
void constraints() {
|
|
function_requires< ReversibleContainerConcept<RandomAccessContainer> >();
|
|
function_requires< RandomAccessIteratorConcept<const_iterator> >();
|
|
function_requires<
|
|
RandomAccessIteratorConcept<const_reverse_iterator> >();
|
|
|
|
const_constraints(c);
|
|
}
|
|
void const_constraints(const RandomAccessContainer& cc) {
|
|
const_reference r = cc[n];
|
|
ignore_unused_variable_warning(r);
|
|
}
|
|
RandomAccessContainer c;
|
|
size_type n;
|
|
};
|
|
|
|
template <class RandomAccessContainer>
|
|
struct Mutable_RandomAccessContainerConcept
|
|
{
|
|
typedef typename RandomAccessContainer::size_type size_type;
|
|
typedef typename RandomAccessContainer::reference reference;
|
|
typedef typename RandomAccessContainer::iterator iterator;
|
|
typedef typename RandomAccessContainer::reverse_iterator reverse_iterator;
|
|
|
|
void constraints() {
|
|
function_requires<
|
|
RandomAccessContainerConcept<RandomAccessContainer> >();
|
|
function_requires<
|
|
Mutable_ReversibleContainerConcept<RandomAccessContainer> >();
|
|
function_requires< Mutable_RandomAccessIteratorConcept<iterator> >();
|
|
function_requires<
|
|
Mutable_RandomAccessIteratorConcept<reverse_iterator> >();
|
|
|
|
reference r = c[i];
|
|
ignore_unused_variable_warning(r);
|
|
}
|
|
size_type i;
|
|
RandomAccessContainer c;
|
|
};
|
|
|
|
// A Sequence is inherently mutable
|
|
template <class Sequence>
|
|
struct SequenceConcept
|
|
{
|
|
|
|
typedef typename Sequence::reference reference;
|
|
typedef typename Sequence::const_reference const_reference;
|
|
|
|
void constraints() {
|
|
// Matt Austern's book puts DefaultConstructible here, the C++
|
|
// standard places it in Container
|
|
// function_requires< DefaultConstructible<Sequence> >();
|
|
function_requires< Mutable_ForwardContainerConcept<Sequence> >();
|
|
function_requires< DefaultConstructibleConcept<Sequence> >();
|
|
|
|
Sequence
|
|
c(n),
|
|
c2(n, t),
|
|
c3(first, last);
|
|
|
|
c.insert(p, t);
|
|
c.insert(p, n, t);
|
|
c.insert(p, first, last);
|
|
|
|
c.erase(p);
|
|
c.erase(p, q);
|
|
|
|
reference r = c.front();
|
|
|
|
ignore_unused_variable_warning(c);
|
|
ignore_unused_variable_warning(c2);
|
|
ignore_unused_variable_warning(c3);
|
|
ignore_unused_variable_warning(r);
|
|
const_constraints(c);
|
|
}
|
|
void const_constraints(const Sequence& c) {
|
|
const_reference r = c.front();
|
|
ignore_unused_variable_warning(r);
|
|
}
|
|
typename Sequence::value_type t;
|
|
typename Sequence::size_type n;
|
|
typename Sequence::value_type* first, *last;
|
|
typename Sequence::iterator p, q;
|
|
};
|
|
|
|
template <class FrontInsertionSequence>
|
|
struct FrontInsertionSequenceConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< SequenceConcept<FrontInsertionSequence> >();
|
|
|
|
c.push_front(t);
|
|
c.pop_front();
|
|
}
|
|
FrontInsertionSequence c;
|
|
typename FrontInsertionSequence::value_type t;
|
|
};
|
|
|
|
template <class BackInsertionSequence>
|
|
struct BackInsertionSequenceConcept
|
|
{
|
|
typedef typename BackInsertionSequence::reference reference;
|
|
typedef typename BackInsertionSequence::const_reference const_reference;
|
|
|
|
void constraints() {
|
|
function_requires< SequenceConcept<BackInsertionSequence> >();
|
|
|
|
c.push_back(t);
|
|
c.pop_back();
|
|
reference r = c.back();
|
|
ignore_unused_variable_warning(r);
|
|
}
|
|
void const_constraints(const BackInsertionSequence& cc) {
|
|
const_reference r = cc.back();
|
|
ignore_unused_variable_warning(r);
|
|
};
|
|
BackInsertionSequence c;
|
|
typename BackInsertionSequence::value_type t;
|
|
};
|
|
|
|
template <class AssociativeContainer>
|
|
struct AssociativeContainerConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< ForwardContainerConcept<AssociativeContainer> >();
|
|
function_requires< DefaultConstructibleConcept<AssociativeContainer> >();
|
|
|
|
i = c.find(k);
|
|
r = c.equal_range(k);
|
|
c.erase(k);
|
|
c.erase(i);
|
|
c.erase(r.first, r.second);
|
|
const_constraints(c);
|
|
}
|
|
void const_constraints(const AssociativeContainer& cc) {
|
|
ci = cc.find(k);
|
|
n = cc.count(k);
|
|
cr = cc.equal_range(k);
|
|
}
|
|
typedef typename AssociativeContainer::iterator iterator;
|
|
typedef typename AssociativeContainer::const_iterator const_iterator;
|
|
|
|
AssociativeContainer c;
|
|
iterator i;
|
|
std::pair<iterator,iterator> r;
|
|
const_iterator ci;
|
|
std::pair<const_iterator,const_iterator> cr;
|
|
typename AssociativeContainer::key_type k;
|
|
typename AssociativeContainer::size_type n;
|
|
};
|
|
|
|
template <class UniqueAssociativeContainer>
|
|
struct UniqueAssociativeContainerConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< AssociativeContainerConcept<UniqueAssociativeContainer> >();
|
|
|
|
UniqueAssociativeContainer c(first, last);
|
|
|
|
pos_flag = c.insert(t);
|
|
c.insert(first, last);
|
|
|
|
ignore_unused_variable_warning(c);
|
|
}
|
|
std::pair<typename UniqueAssociativeContainer::iterator, bool> pos_flag;
|
|
typename UniqueAssociativeContainer::value_type t;
|
|
typename UniqueAssociativeContainer::value_type* first, *last;
|
|
};
|
|
|
|
template <class MultipleAssociativeContainer>
|
|
struct MultipleAssociativeContainerConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< AssociativeContainerConcept<MultipleAssociativeContainer> >();
|
|
|
|
MultipleAssociativeContainer c(first, last);
|
|
|
|
pos = c.insert(t);
|
|
c.insert(first, last);
|
|
|
|
ignore_unused_variable_warning(c);
|
|
ignore_unused_variable_warning(pos);
|
|
}
|
|
typename MultipleAssociativeContainer::iterator pos;
|
|
typename MultipleAssociativeContainer::value_type t;
|
|
typename MultipleAssociativeContainer::value_type* first, *last;
|
|
};
|
|
|
|
template <class SimpleAssociativeContainer>
|
|
struct SimpleAssociativeContainerConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< AssociativeContainerConcept<SimpleAssociativeContainer> >();
|
|
typedef typename SimpleAssociativeContainer::key_type key_type;
|
|
typedef typename SimpleAssociativeContainer::value_type value_type;
|
|
typedef typename require_same<key_type, value_type>::type req;
|
|
}
|
|
};
|
|
|
|
template <class SimpleAssociativeContainer>
|
|
struct PairAssociativeContainerConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< AssociativeContainerConcept<SimpleAssociativeContainer> >();
|
|
typedef typename SimpleAssociativeContainer::key_type key_type;
|
|
typedef typename SimpleAssociativeContainer::value_type value_type;
|
|
typedef typename SimpleAssociativeContainer::mapped_type mapped_type;
|
|
typedef std::pair<const key_type, mapped_type> required_value_type;
|
|
typedef typename require_same<value_type, required_value_type>::type req;
|
|
}
|
|
};
|
|
|
|
template <class SortedAssociativeContainer>
|
|
struct SortedAssociativeContainerConcept
|
|
{
|
|
void constraints() {
|
|
function_requires< AssociativeContainerConcept<SortedAssociativeContainer> >();
|
|
function_requires< ReversibleContainerConcept<SortedAssociativeContainer> >();
|
|
|
|
SortedAssociativeContainer
|
|
c(kc),
|
|
c2(first, last),
|
|
c3(first, last, kc);
|
|
|
|
p = c.upper_bound(k);
|
|
p = c.lower_bound(k);
|
|
r = c.equal_range(k);
|
|
|
|
c.insert(p, t);
|
|
|
|
ignore_unused_variable_warning(c);
|
|
ignore_unused_variable_warning(c2);
|
|
ignore_unused_variable_warning(c3);
|
|
}
|
|
void const_constraints(const SortedAssociativeContainer& c) {
|
|
kc = c.key_comp();
|
|
vc = c.value_comp();
|
|
|
|
cp = c.upper_bound(k);
|
|
cp = c.lower_bound(k);
|
|
cr = c.equal_range(k);
|
|
}
|
|
typename SortedAssociativeContainer::key_compare kc;
|
|
typename SortedAssociativeContainer::value_compare vc;
|
|
typename SortedAssociativeContainer::value_type t;
|
|
typename SortedAssociativeContainer::key_type k;
|
|
typedef typename SortedAssociativeContainer::iterator iterator;
|
|
typedef typename SortedAssociativeContainer::const_iterator const_iterator;
|
|
iterator p;
|
|
const_iterator cp;
|
|
std::pair<iterator,iterator> r;
|
|
std::pair<const_iterator,const_iterator> cr;
|
|
typename SortedAssociativeContainer::value_type* first, *last;
|
|
};
|
|
|
|
// HashedAssociativeContainer
|
|
|
|
} // namespace boost
|
|
|
|
#endif // BOOST_CONCEPT_CHECKS_HPP
|
|
|