]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) |
2 | // (C) Copyright 2005-2007 Jonathan Turkanis | |
3 | // (C) Copyright David Abrahams 2004. | |
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) | |
6 | ||
7 | // See http://www.boost.org/libs/iostreams for documentation. | |
8 | ||
9 | #ifndef BOOST_IOSTREAMS_DETAIL_IS_DEREFERENCEABLE_HPP_INCLUDED | |
10 | #define BOOST_IOSTREAMS_DETAIL_IS_DEREFERENCEABLE_HPP_INCLUDED | |
11 | ||
12 | # include <boost/type_traits/remove_cv.hpp> | |
13 | # include <boost/mpl/aux_/lambda_support.hpp> | |
14 | # include <boost/mpl/bool.hpp> | |
15 | # include <boost/detail/workaround.hpp> | |
16 | ||
17 | namespace boost { namespace iostreams { namespace detail { | |
18 | ||
19 | // is_dereferenceable<T> metafunction | |
20 | // | |
21 | // Requires: Given x of type T&, if the expression *x is well-formed | |
22 | // it must have complete type; otherwise, it must neither be ambiguous | |
23 | // nor violate access. | |
24 | ||
25 | // This namespace ensures that ADL doesn't mess things up. | |
26 | namespace is_dereferenceable_ | |
27 | { | |
28 | // a type returned from operator* when no increment is found in the | |
29 | // type's own namespace | |
30 | struct tag {}; | |
31 | ||
32 | // any soaks up implicit conversions and makes the following | |
33 | // operator* less-preferred than any other such operator that | |
34 | // might be found via ADL. | |
35 | struct any { template <class T> any(T const&); }; | |
36 | ||
37 | // This is a last-resort operator* for when none other is found | |
38 | tag operator*(any const&); | |
39 | ||
40 | # if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3202)) | |
41 | # define BOOST_comma(a,b) (a) | |
42 | # else | |
43 | // In case an operator++ is found that returns void, we'll use ++x,0 | |
44 | tag operator,(tag,int); | |
45 | # define BOOST_comma(a,b) (a,b) | |
46 | # endif | |
47 | ||
48 | // two check overloads help us identify which operator++ was picked | |
49 | char (& check_increment(tag) )[2]; | |
50 | ||
51 | template <class T> | |
52 | char check_increment(T const&); | |
53 | ||
54 | template <class T> | |
55 | struct impl | |
56 | { | |
57 | static typename boost::remove_cv<T>::type& x; | |
58 | ||
59 | BOOST_STATIC_CONSTANT( | |
60 | bool | |
61 | , value = sizeof(is_dereferenceable_::check_increment(BOOST_comma(*x,0))) == 1 | |
62 | ); | |
63 | }; | |
64 | } | |
65 | ||
66 | # undef BOOST_comma | |
67 | ||
68 | template<typename T> | |
69 | struct is_dereferenceable | |
70 | : public ::boost::integral_constant<bool, is_dereferenceable_::impl<T>::value > | |
71 | { | |
72 | BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_dereferenceable,(T)) | |
73 | }; | |
74 | ||
75 | } } | |
76 | ||
77 | ||
78 | } // End namespaces detail, iostreams, boost. | |
79 | ||
80 | #endif // BOOST_IOSTREAMS_DETAIL_IS_DEREFERENCEABLE_HPP_INCLUDED |