summaryrefslogtreecommitdiffstats
blob: fe1a5a13ba6e93fe2a30c136a1ad1327d58b07d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// Boost.Signals library

// Copyright Douglas Gregor 2001-2004. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// For more information, see http://www.boost.org

#ifndef BOOST_SIGNALS_COMMON_HEADER
#define BOOST_SIGNALS_COMMON_HEADER

#ifndef BOOST_SIGNALS_NAMESPACE
#  define BOOST_SIGNALS_NAMESPACE signals
#endif

#include <boost/type_traits/conversion_traits.hpp>
#include <boost/ref.hpp>
#include <boost/signals/detail/config.hpp>

#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_PREFIX
#endif

namespace boost {
  namespace BOOST_SIGNALS_NAMESPACE {
    namespace detail {
      // The unusable class is a placeholder for unused function arguments
      // It is also completely unusable except that it constructable from
      // anything. This helps compilers without partial specialization
      // handle slots returning void.
      struct unusable {
        unusable() {}
      };

      // Determine the result type of a slot call
      template<typename R>
      struct slot_result_type {
        typedef R type;
      };

      template<>
      struct slot_result_type<void> {
        typedef unusable type;
      };

      // Determine if the given type T is a signal
      class signal_base;

      template<typename T>
      struct is_signal {
        BOOST_STATIC_CONSTANT(bool,
          value = (is_convertible<T*, signal_base*>::value));
      };

      /*
       * The IF implementation is temporary code. When a Boost metaprogramming
       * library is introduced, Boost.Signals will use it instead.
       */
      namespace intimate {
        struct SelectThen
        {
          template<typename Then, typename Else>
          struct Result
          {
            typedef Then type;
          };
        };

        struct SelectElse
        {
          template<typename Then, typename Else>
          struct Result
          {
            typedef Else type;
          };
        };

        template<bool Condition>
        struct Selector
        {
          typedef SelectThen type;
        };

        template<>
        struct Selector<false>
        {
          typedef SelectElse type;
        };
      } // end namespace intimate

      template<bool Condition, typename Then, typename Else>
      struct IF
      {
        typedef typename intimate::Selector<Condition>::type select;
        typedef typename select::template Result<Then,Else>::type type;
      };

      // Determine if the incoming argument is a reference_wrapper
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
      template<typename T>
      struct is_ref
      {
        BOOST_STATIC_CONSTANT(bool, value = false);
      };

      template<typename T>
      struct is_ref<reference_wrapper<T> >
      {
        BOOST_STATIC_CONSTANT(bool, value = true);
      };
#else // no partial specialization
      typedef char yes_type;
      typedef double no_type;

      no_type is_ref_tester(...);

      template<typename T>
      yes_type is_ref_tester(reference_wrapper<T>*);

      template<typename T>
      struct is_ref
      {
        static T* t;
        BOOST_STATIC_CONSTANT(bool,
          value = (sizeof(is_ref_tester(t)) == sizeof(yes_type)));
      };
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION

      // A slot can be a signal, a reference to a function object, or a
      // function object.
      struct signal_tag {};
      struct reference_tag {};
      struct value_tag {};

      // Classify the given slot as a signal, a reference-to-slot, or a
      // standard slot
      template<typename S>
      class get_slot_tag {
        typedef typename IF<(is_signal<S>::value),
                            signal_tag,
                            value_tag>::type signal_or_value;

      public:
        typedef typename IF<(is_ref<S>::value),
                            reference_tag,
                            signal_or_value>::type type;
      };

      // Forward declaration needed in lots of places
      class signal_base_impl;
      class bound_objects_visitor;
      class slot_base;
    } // end namespace detail
  } // end namespace BOOST_SIGNALS_NAMESPACE
} // end namespace boost

#ifdef BOOST_HAS_ABI_HEADERS
#  include BOOST_ABI_SUFFIX
#endif

#endif // BOOST_SIGNALS_COMMON_HEADER