ztd.h
Go to the documentation of this file.
1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ZORBA_INTERNAL_ZTD_H
18 #define ZORBA_INTERNAL_ZTD_H
19 
20 #include <cstring>
21 #include <functional>
22 #include <sstream>
23 #include <string>
24 
25 #include <zorba/config.h>
26 
27 #include "type_traits.h"
28 
29 ///////////////////////////////////////////////////////////////////////////////
30 
31 namespace zorba {
32 namespace internal {
33 namespace ztd {
34 
35 ////////// tr1 ////////////////////////////////////////////////////////////////
36 
37 /**
38  * \internal
39  * Base class for SFINAE (Substitution Failure Is Not An Error) types.
40  */
41 class sfinae_base {
42 protected:
43  typedef char no;
44  typedef char yes[2];
45 public:
47 };
48 
49 /**
50  * \internal
51  * Declares a class that can be used to determine whether a given type \c T has
52  * a particular member function with a certain signature.
53  * For example:
54  * \code
55  * ZORBA_DECL_HAS_MEM_FN( c_str );
56  *
57  * template<typename T> inline
58  * typename enable_if<has_c_str<T,char const* (T::*)() const>::value,
59  * std::string>::type
60  * to_string( T const &t ) {
61  * // case where T has c_str()
62  * }
63  *
64  * template<typename T> inline
65  * typename enable_if<!has_c_str<T,char const* (T::*)() const>::value,
66  * std::string>::type
67  * to_string( T const &t ) {
68  * // case where T does not have c_str()
69  * }
70  * \endcode
71  * \hideinitializer
72  */
73 #define ZORBA_DECL_HAS_MEM_FN(FN_NAME) \
74  template<typename T,typename S> \
75  class has_##FN_NAME : public sfinae_base { \
76  template<typename SignatureType,SignatureType> struct type_check; \
77  template<class U> static yes& test(type_check<S,&U::FN_NAME>*); \
78  template<class U> static no& test(...); \
79  public: \
80  static bool const value = sizeof( test<T>(0) ) == sizeof( yes ); \
81  }
82 
83 /**
84  * \internal
85  * This namespace is used only to bundle the implementation details for
86  * implementing \c has_insertion_operator<T>.
87  * This implementation is based on http://stackoverflow.com/questions/4434569/
88  */
89 namespace has_insertion_operator_impl {
90  typedef char no;
91  typedef char yes[2];
92 
93  /**
94  * This dummy class is used to make the matching of the dummy operator<<()
95  * \e worse than the global \c operator<<(), if any.
96  */
97  struct any_t {
98  template<typename T> any_t( T const& );
99  };
100 
101  /**
102  * This dummy operator is matched only when there is \e no global
103  * operator<<() otherwise declared for type \c T.
104  *
105  * @return Returns a \c no that selects defined(no).
106  */
107  no operator<<( std::ostream const&, any_t const& );
108 
109  /**
110  * This function is matched only when there \e is a global \c operator<<()
111  * declared for type \c T because \c operator<<()'s return type is
112  * \c std::ostream&.
113  *
114  * @return Returns a yes& whose \c sizeof() equals \c sizeof(yes).
115  */
116  yes& defined( std::ostream& );
117 
118  /**
119  * This function is matched only when the dummy \c operator<<() is matched.
120  *
121  * @return Returns a no whose \c sizeof() equals \c sizeof(no).
122  */
123  no defined( no );
124 
125  /**
126  * The implementation class that can be used to determine whether a given
127  * type \c T has a global <code>std::ostream& operator<<(std::ostream&,T
128  * const&)</code> defined for it. However, do not use this class directly.
129  *
130  * @tparam T The type to check.
131  */
132  template<typename T>
134  static std::ostream &s;
135  static T const &t;
136  public:
137  /**
138  * This is \c true only when the type \c T has a global \c operator<<()
139  * declared for it.
140  * \hideinitializer
141  */
142  static bool const value = sizeof( defined( s << t ) ) == sizeof( yes );
143  };
144 } // namespace has_insertion_operator_impl
145 
146 /**
147  * \internal
148  * A class that can be used to determine whether a given type \c T has a global
149  * <code>std::ostream& operator<<(std::ostream&,T const&)</code> defined for
150  * it.
151  * For example:
152  * \code
153  * template<typename T> inline
154  * typename enable_if<has_insertion_operator<T>::value,std::string>::value
155  * to_string( T const &t ) {
156  * // case where T has operator<<(ostream&,T const&)
157  * }
158  * \endcode
159  *
160  * @tparam T The type to check.
161  */
162 template<typename T>
165 {
166 };
167 
168 ////////// c_str() /////////////////////////////////////////////////////////////
169 
170 /**
171  * \internal
172  * Gets the \c char* to the given string.
173  *
174  * @tparam OutputStringType The string's type.
175  * @param s The string to get the \c char* of.
176  * @return Returns said \c char*.
177  */
178 template<class StringType> inline
179 typename StringType::const_pointer c_str( StringType const &s ) {
180  return s.c_str();
181 }
182 
183 /**
184  * \internal
185  * Specialization of global c_str() for \c char* argument.
186  *
187  * @param s The C string to get the \c char* of.
188  * @return Returns said \c char*.
189  */
190 inline char const* c_str( char const *s ) {
191  return s;
192 }
193 
194 ////////// destroy_delete (for unique_ptr) ////////////////////////////////////
195 
196 /**
197  * A deleter class that can be used with unique_ptr. Instead of calling \c
198  * delete on the pointed-to object, it calls its \c destroy() member function.
199  */
200 template<typename T>
203 
204  /**
205  * Copy constructor.
206  *
207  * @tparam U The delete type of the deleter to copy-construct from such that
208  * \c U* is convertible to \c T*.
209  */
210  template<typename U>
212  typename
213  std::enable_if<ZORBA_TR1_NS::is_convertible<U*,T*>::value>::type* = 0 )
214  {
215  }
216 
217  /**
218  * Calls the \c destroy() member function of the pointed-to object.
219  *
220  * @param p A pointer to the object.
221  */
222  void operator()( T *p ) {
223  if ( p )
224  p->destroy();
225  }
226 };
227 
228 ////////// less<char const*> ///////////////////////////////////////////////////
229 
230 // This declaration exists only to declare that less is a template class.
231 template<typename T> struct less {
232 };
233 
234 /**
235  * \internal
236  * Specialize the binary_function "less" so that C-style strings (char const*)
237  * will work properly with STL containers.
238  *
239  * See also: Bjarne Stroustrup. "The C++ Programming Language, 3rd ed."
240  * Addison-Wesley, Reading, MA, 1997. p. 468.
241  */
242 template<> struct less<char const*> :
243  std::binary_function<char const*,char const*,bool>
244 {
245  less() { }
246  // This default constructor doesn't need to be defined, but g++ complains if
247  // it isn't and you try to define a "const less" object.
248 
249  result_type
250  operator()( first_argument_type a, second_argument_type b ) const {
251  return std::strcmp( a, b ) < 0;
252  }
253 };
254 
255 ////////// To-string conversion ////////////////////////////////////////////////
256 
258 ZORBA_DECL_HAS_MEM_FN( str );
259 ZORBA_DECL_HAS_MEM_FN( toString );
260 
261 /**
262  * \internal
263  * Converts an object to its string representation.
264  *
265  * @tparam T The object type that:
266  * - is not a pointer
267  * - has an <code>ostream& operator&lt;&lt;(ostream&,T const&)</code> defined
268  * @param t The object.
269  * @return Returns a string representation of the object.
270  */
271 template<typename T> inline
273  && has_insertion_operator<T>::value,
274  std::string>::type
275 to_string( T const &t ) {
276  std::ostringstream o;
277  o << t;
278  return o.str();
279 }
280 
281 /**
282  * \internal
283  * Specialization of \c to_string() for class types that have a \c c_str()
284  * member function, i.e., string types.
285  *
286  * @tparam T The class type that:
287  * - has no <code>ostream& operator&lt;&lt;(ostream&,T const&)</code> defined
288  * - has <code>char const* T::c_str() const</code> defined
289  * @param t The object.
290  * @return Returns a string representation of the object.
291  */
292 template<class T> inline
294  && has_c_str<T,char const* (T::*)() const>::value,
295  std::string>::type
296 to_string( T const &t ) {
297  return t.c_str();
298 }
299 
300 /**
301  * \internal
302  * Specialization of \c to_string() for class types that have a \c str()
303  * member function.
304  *
305  * @tparam T The class type that:
306  * - has no <code>ostream& operator&lt;&lt;(ostream&,T const&)</code> defined
307  * - has no <code>char const* T::c_str() const</code> defined
308  * - has no <code>std::string T::toString() const</code> defined
309  * - has <code>std::string T::str() const</code> defined
310  * @param t The object.
311  * @return Returns a string representation of the object.
312  */
313 template<class T> inline
315  && !has_c_str<T,char const* (T::*)() const>::value
316  && has_str<T,std::string (T::*)() const>::value
317  && !has_toString<T,std::string (T::*)() const>::value,
318  std::string>::type
319 to_string( T const &t ) {
320  return t.str();
321 }
322 
323 /**
324  * \internal
325  * Specialization of \c to_string() for class types that have a \c toString()
326  * member function.
327  *
328  * @tparam T The class type that:
329  * - has no <code>ostream& operator&lt;&lt;(ostream&,T const&)</code> defined
330  * - has no <code>char const* T::c_str() const</code> defined
331  * - has no <code>std::string T::str() const</code> defined
332  * - has <code>std::string T::toString() const</code> defined
333  * @param t The object.
334  * @return Returns a string representation of the object.
335  */
336 template<class T> inline
338  && !has_c_str<T,char const* (T::*)() const>::value
339  && !has_str<T,std::string (T::*)() const>::value
340  && has_toString<T,std::string (T::*)() const>::value,
341  std::string>::type
342 to_string( T const &t ) {
343  return t.toString();
344 }
345 
346 /**
347  * \internal
348  * Specialization of \c to_string() for pointer types.
349  *
350  * @tparam T The pointer type.
351  * @param p The pointer.
352  * @return If \a p is not \c NULL, returns the result of \c to_string(*p);
353  * otherwise returns \c "<null>".
354  */
355 template<typename T> inline
357 to_string( T p ) {
358  typedef typename ZORBA_TR1_NS::remove_pointer<T>::type const* T_const_ptr;
359  return p ? to_string( *static_cast<T_const_ptr>( p ) ) : "<null>";
360 }
361 
362 /**
363  * \internal
364  * Specialization of \c to_string() for C strings.
365  *
366  * @param s The C string.
367  * @return Returns a string representation of the object.
368  */
369 inline std::string to_string( char const *s ) {
370  return s ? s : "<null>";
371 }
372 
373 ////////// misc ///////////////////////////////////////////////////////////////
374 
375 /**
376  * Helper class for implementing a solution to the "explicit bool conversion"
377  * problem. The canonical use is of the form:
378  * \code
379  * class your_class {
380  * // ...
381  * operator explicit_bool::type() const {
382  * return explicit_bool::value_of( some_expression );
383  * }
384  * };
385  * \endcode
386  *
387  * See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2333.html
388  */
390  struct pointer_conversion { int valid; };
391 public:
392  typedef int pointer_conversion::*type;
393 
394  /**
395  * Gets the explicit \c bool value for \c false.
396  *
397  * @return Returns said value.
398  */
399  static type false_value() {
400  return 0;
401  }
402 
403  /**
404  * Gets the explicit \c bool value for \c true.
405  *
406  * @return Returns said value.
407  */
408  static type true_value() {
409  return &pointer_conversion::valid;
410  }
411 
412  /**
413  * Converts the the built-in \c bool value to an explicit \c bool value.
414  *
415  * @param value The \c bool value to convert.
416  * @return Return said value.
417  */
418  static type value_of( bool value ) {
419  return value ? true_value() : false_value();
420  }
421 };
422 
423 ///////////////////////////////////////////////////////////////////////////////
424 
425 } // namespace ztd
426 } // namespace internal
427 } // namespace zorba
428 #endif /* ZORBA_INTERNAL_ZTD_H */
429 /* vim:set et sw=2 ts=2: */
blog comments powered by Disqus