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 ::zorba::internal::ztd::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/q/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 #define ZORBA_HAS_C_STR(T) \
262  ::zorba::internal::ztd::has_c_str<T,char const* (T::*)() const>::value
263 
264 #define ZORBA_IS_STRING(T) ZORBA_HAS_C_STR(T)
265 
266 /**
267  * \internal
268  * Tests whether a given type \a T is a C string type.
269  *
270  * @tparam T The type to check.
271  */
272 template<typename T>
273 class is_c_string {
274  typedef typename ZORBA_TR1_NS::remove_pointer<T>::type T_base;
275  typedef typename ZORBA_TR1_NS::add_const<T_base>::type T_base_const;
276 public:
277  static bool const value =
278  ZORBA_TR1_NS::is_same<T_base_const*,char const*>::value
279  || ZORBA_TR1_NS::is_same<T_base_const*,unsigned char const*>::value
280  || ZORBA_TR1_NS::is_same<T_base_const*,signed char const*>::value;
281 };
282 
283 /**
284  * \internal
285  * Converts an object to its string representation.
286  *
287  * @tparam T The object type that:
288  * - is not an array
289  * - is not a pointer
290  * - has an <code>ostream& operator&lt;&lt;(ostream&,T const&)</code> defined
291  * @param t The object.
292  * @return Returns a string representation of the object.
293  */
294 template<typename T> inline
296  && !ZORBA_TR1_NS::is_pointer<T>::value
298  std::string>::type
299 to_string( T const &t ) {
300  std::ostringstream o;
301  o << t;
302  return o.str();
303 }
304 
305 /**
306  * \internal
307  * Specialization of \c to_string() for class types that have a \c c_str()
308  * member function, i.e., string types.
309  *
310  * @tparam T The class type that:
311  * - has no <code>ostream& operator&lt;&lt;(ostream&,T const&)</code> defined
312  * - has <code>char const* T::c_str() const</code> defined
313  * @param t The object.
314  * @return Returns a string representation of the object.
315  */
316 template<class T> inline
318  && ZORBA_HAS_C_STR(T),
319  std::string>::type
320 to_string( T const &t ) {
321  return t.c_str();
322 }
323 
324 /**
325  * \internal
326  * Specialization of \c to_string() for class types that have a \c str()
327  * member function.
328  *
329  * @tparam T The class type that:
330  * - has no <code>ostream& operator&lt;&lt;(ostream&,T const&)</code> defined
331  * - has no <code>char const* T::c_str() const</code> defined
332  * - has no <code>std::string T::toString() const</code> defined
333  * - has <code>std::string T::str() const</code> defined
334  * @param t The object.
335  * @return Returns a string representation of the object.
336  */
337 template<class T> inline
339  && !ZORBA_HAS_C_STR(T)
340  && has_str<T,std::string (T::*)() const>::value
341  && !has_toString<T,std::string (T::*)() const>::value,
342  std::string>::type
343 to_string( T const &t ) {
344  return t.str();
345 }
346 
347 /**
348  * \internal
349  * Specialization of \c to_string() for class types that have a \c toString()
350  * member function.
351  *
352  * @tparam T The class type that:
353  * - has no <code>ostream& operator&lt;&lt;(ostream&,T const&)</code> defined
354  * - has no <code>char const* T::c_str() const</code> defined
355  * - has no <code>std::string T::str() const</code> defined
356  * - has <code>std::string T::toString() const</code> defined
357  * @param t The object.
358  * @return Returns a string representation of the object.
359  */
360 template<class T> inline
362  && !ZORBA_HAS_C_STR(T)
363  && !has_str<T,std::string (T::*)() const>::value
364  && has_toString<T,std::string (T::*)() const>::value,
365  std::string>::type
366 to_string( T const &t ) {
367  return t.toString();
368 }
369 
370 /**
371  * \internal
372  * Specialization of \c to_string() for pointer types other than C strings.
373  *
374  * @tparam T The pointer type.
375  * @param p The pointer.
376  * @return If \a p is not \c NULL, returns the result of \c to_string(*p);
377  * otherwise returns \c "<null>".
378  */
379 template<typename T> inline
381  && !is_c_string<T>::value,
382  std::string>::type
383 to_string( T p ) {
384  typedef typename ZORBA_TR1_NS::remove_pointer<T>::type T_base;
385  typedef typename ZORBA_TR1_NS::add_const<T_base>::type T_base_const;
386  return p ? to_string( *static_cast<T_base_const*>( p ) ) : "<null>";
387 }
388 
389 /**
390  * \internal
391  * Specialization of \c to_string() for C strings.
392  *
393  * @param s The C string.
394  * @return Returns a string representation of the object.
395  */
396 inline std::string to_string( char const *s ) {
397  return s ? s : "<null>";
398 }
399 
400 /**
401  * \internal
402  * Specialization of \c to_string() for C strings.
403  *
404  * @param s The C string.
405  * @return Returns a string representation of the object.
406  */
407 inline std::string to_string( unsigned char const *s ) {
408  return s ? reinterpret_cast<char const*>( s ) : "<null>";
409 }
410 
411 ////////// misc ///////////////////////////////////////////////////////////////
412 
413 /**
414  * Helper class for implementing a solution to the "explicit bool conversion"
415  * problem. The canonical use is of the form:
416  * \code
417  * class your_class {
418  * // ...
419  * operator explicit_bool::type() const {
420  * return explicit_bool::value_of( some_expression );
421  * }
422  * };
423  * \endcode
424  *
425  * See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2333.html
426  */
428  struct pointer_conversion { int valid; };
429 public:
430  typedef int pointer_conversion::*type;
431 
432  /**
433  * Gets the explicit \c bool value for \c false.
434  *
435  * @return Returns said value.
436  */
437  static type false_value() {
438  return 0;
439  }
440 
441  /**
442  * Gets the explicit \c bool value for \c true.
443  *
444  * @return Returns said value.
445  */
446  static type true_value() {
447  return &pointer_conversion::valid;
448  }
449 
450  /**
451  * Converts the given value to an explicit \c bool value.
452  *
453  * @tparam T The type of the value to convert.
454  * @param value The value to convert.
455  * @return Return said value.
456  */
457  template<typename T> static
459  type>::type
460  value_of( T const &value ) {
461  //
462  // Using a template here eliminates a MSVC++ 4800 warning:
463  // "forcing value to 'true' or 'false' (performance warning)"
464  //
465  return value ? true_value() : false_value();
466  }
467 };
468 
469 ///////////////////////////////////////////////////////////////////////////////
470 
471 } // namespace ztd
472 } // namespace internal
473 } // namespace zorba
474 #endif /* ZORBA_INTERNAL_ZTD_H */
475 /* vim:set et sw=2 ts=2: */