Moved concept checks into a separate class, which makes MSVC better at dealing with them

[SVN r12255]
This commit is contained in:
Dave Abrahams 2002-01-09 12:14:16 +00:00
parent ebcb4d861a
commit 57251d58cc

View File

@ -12,6 +12,9 @@
// //
// Revision History: // Revision History:
// 08 Jan 2001 David Abrahams
// Moved concept checks into a separate class, which makes MSVC
// better at dealing with them.
// 07 Jan 2001 David Abrahams // 07 Jan 2001 David Abrahams
// Choose proxy for operator->() only if the reference type is not a reference. // Choose proxy for operator->() only if the reference type is not a reference.
// Updated workarounds for __MWERKS__ == 0x2406 // Updated workarounds for __MWERKS__ == 0x2406
@ -554,7 +557,7 @@ namespace detail {
// An associative list is a list of key-value pairs. The list is // An associative list is a list of key-value pairs. The list is
// built out of cons_type's and is terminated by end_of_list. // built out of cons_type's and is terminated by end_of_list.
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(__BORLANDC__) # if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(__BORLANDC__)
template <class AssocList, class Key> template <class AssocList, class Key>
struct find_param; struct find_param;
@ -583,7 +586,7 @@ namespace detail {
typedef typename find_param_helper1<AssocList>::type select1; typedef typename find_param_helper1<AssocList>::type select1;
typedef typename select1::template select<AssocList, Key>::type type; typedef typename select1::template select<AssocList, Key>::type type;
}; };
#else # else
template <class AssocList, class Key> struct find_param; template <class AssocList, class Key> struct find_param;
template <class Key> template <class Key>
@ -600,7 +603,7 @@ namespace detail {
struct find_param<detail::cons_type< detail::cons_type<Key1, Value>, Rest>, Key2> { struct find_param<detail::cons_type< detail::cons_type<Key1, Value>, Rest>, Key2> {
typedef typename find_param<Rest, Key2>::type type; typedef typename find_param<Rest, Key2>::type type;
}; };
#endif # endif
struct make_named_arg { struct make_named_arg {
template <class Key, class Value> template <class Key, class Value>
@ -617,26 +620,26 @@ namespace detail {
enum { value = is_convertible<Value, named_template_param_base>::value }; enum { value = is_convertible<Value, named_template_param_base>::value };
}; };
#if defined(__MWERKS__) && __MWERKS__ <= 0x2406 // workaround for broken is_convertible implementation # if defined(__MWERKS__) && __MWERKS__ <= 0x2406 // workaround for broken is_convertible implementation
template <class T> struct is_named_parameter<value_type_is<T> > { enum { value = true }; }; template <class T> struct is_named_parameter<value_type_is<T> > { enum { value = true }; };
template <class T> struct is_named_parameter<reference_is<T> > { enum { value = true }; }; template <class T> struct is_named_parameter<reference_is<T> > { enum { value = true }; };
template <class T> struct is_named_parameter<pointer_is<T> > { enum { value = true }; }; template <class T> struct is_named_parameter<pointer_is<T> > { enum { value = true }; };
template <class T> struct is_named_parameter<difference_type_is<T> > { enum { value = true }; }; template <class T> struct is_named_parameter<difference_type_is<T> > { enum { value = true }; };
template <class T> struct is_named_parameter<iterator_category_is<T> > { enum { value = true }; }; template <class T> struct is_named_parameter<iterator_category_is<T> > { enum { value = true }; };
#endif # endif
template <class Key, class Value> template <class Key, class Value>
struct make_arg { struct make_arg {
#ifdef __BORLANDC__ # ifdef __BORLANDC__
// Borland C++ doesn't like the extra indirection of is_named_parameter // Borland C++ doesn't like the extra indirection of is_named_parameter
typedef typename typedef typename
if_true<(is_convertible<Value,named_template_param_base>::value)>:: if_true<(is_convertible<Value,named_template_param_base>::value)>::
template then<make_named_arg, make_key_value>::type Make; template then<make_named_arg, make_key_value>::type Make;
#else # else
enum { is_named = is_named_parameter<Value>::value }; enum { is_named = is_named_parameter<Value>::value };
typedef typename if_true<(is_named)>::template typedef typename if_true<(is_named)>::template
then<make_named_arg, make_key_value>::type Make; then<make_named_arg, make_key_value>::type Make;
#endif # endif
typedef typename Make::template select<Key, Value>::type type; typedef typename Make::template select<Key, Value>::type type;
}; };
@ -727,6 +730,29 @@ namespace detail {
difference_type, pointer, reference> type; difference_type, pointer, reference> type;
}; };
// This is really a partial concept check for iterators. Should it
// be moved or done differently?
template <class Category, class Value, class Difference, class Pointer, class Reference>
struct validator
{
BOOST_STATIC_CONSTANT(
bool, is_input_or_output_iter
= (boost::is_convertible<Category*,std::input_iterator_tag*>::value
| boost::is_convertible<Category*,std::output_iterator_tag*>::value));
// Iterators should satisfy one of the known categories
BOOST_STATIC_ASSERT(is_input_or_output_iter);
// Iterators >= ForwardIterator must produce real references
// as required by the C++ standard requirements in Table 74.
BOOST_STATIC_CONSTANT(
bool, forward_iter_with_real_reference
= ((!boost::is_convertible<Category*,std::forward_iterator_tag*>::value)
| boost::is_same<Reference,Value&>::value
| boost::is_same<Reference,typename add_const<Value>::type&>::value));
BOOST_STATIC_ASSERT(forward_iter_with_real_reference);
};
} // namespace detail } // namespace detail
@ -738,8 +764,6 @@ namespace detail {
# define BOOST_ARG_DEPENDENT_TYPENAME # define BOOST_ARG_DEPENDENT_TYPENAME
# endif # endif
template <class T> struct undefined;
//============================================================================ //============================================================================
//iterator_adaptor - Adapts a generic piece of data as an iterator. Adaptation //iterator_adaptor - Adapts a generic piece of data as an iterator. Adaptation
// is especially easy if the data being adapted is itself an iterator // is especially easy if the data being adapted is itself an iterator
@ -800,25 +824,14 @@ struct iterator_adaptor :
typedef Policies policies_type; typedef Policies policies_type;
private: private:
BOOST_STATIC_CONSTANT(bool, is_input_or_output_iter typedef detail::validator<
= (boost::is_convertible<iterator_category*,std::input_iterator_tag*>::value iterator_category,value_type,difference_type,pointer,reference
| boost::is_convertible<iterator_category*,std::output_iterator_tag*>::value)); > concept_check;
// Iterators should satisfy one of the known categories
BOOST_STATIC_ASSERT(is_input_or_output_iter);
// Iterators >= ForwardIterator must produce real references
// as required by the C++ standard requirements in Table 74.
BOOST_STATIC_CONSTANT(bool, forward_iter_with_real_reference
= ((!boost::is_convertible<iterator_category*,std::forward_iterator_tag*>::value)
| boost::is_same<reference,value_type&>::value
| boost::is_same<reference,const value_type&>::value));
// This check gives incorrect results in iter_traits_gen_test.cpp
BOOST_STATIC_ASSERT(forward_iter_with_real_reference);
public: public:
iterator_adaptor() { } iterator_adaptor()
{
}
explicit explicit
iterator_adaptor(const Base& it, const Policies& p = Policies()) iterator_adaptor(const Base& it, const Policies& p = Policies())