Advertisement
Radfler

::as_string

May 4th, 2016
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.99 KB | None | 0 0
  1. #include <sstream>
  2. #include <string>
  3. #include <type_traits>
  4. #include <utility>
  5.  
  6. namespace details {
  7.  
  8.     namespace impl {
  9.  
  10.         template<typename T>
  11.         struct has_member_to_string {
  12.  
  13.         private:
  14.  
  15.             template<typename U>
  16.             using test_type = decltype(std::declval<U>().to_string());
  17.  
  18.             template<typename U>
  19.             static std::true_type test(test_type<U>*);
  20.  
  21.             template<typename U>
  22.             static std::false_type test(...);
  23.  
  24.         public:
  25.  
  26.             using type = decltype(test<T>(nullptr));
  27.  
  28.         };
  29.  
  30.         using std::to_string;
  31.  
  32.         template<typename T>
  33.         struct has_non_member_to_string {
  34.  
  35.         private:
  36.  
  37.             template<typename U>
  38.             using test_type = decltype(to_string(std::declval<U>()));
  39.  
  40.             template<typename U>
  41.             static std::true_type test(test_type<U>*);
  42.  
  43.             template<typename U>
  44.             static std::false_type test(...);
  45.  
  46.         public:
  47.  
  48.             using type = decltype(test<T>(nullptr));
  49.  
  50.         };
  51.  
  52.     }
  53.  
  54.     template<typename T>
  55.     using has_member_to_string = typename impl::has_member_to_string<T>::type;
  56.  
  57.     template<typename T>
  58.     using has_non_member_to_string = typename impl::has_non_member_to_string<T>::type;
  59.    
  60.     template<typename T>
  61.     using is_convertible_to_string = std::is_convertible<T, std::string>;
  62.  
  63.     template<typename T>
  64.     using is_first_overload = std::bool_constant<is_convertible_to_string<T>::value>;
  65.  
  66.     template<typename T>
  67.     using is_second_overload = std::bool_constant<has_member_to_string<T>::value && !is_convertible_to_string<T>::value>;
  68.  
  69.     template<typename T>
  70.     using is_third_overload = std::bool_constant<has_non_member_to_string<T>::value && !has_member_to_string<T>::value && !is_convertible_to_string<T>::value>;
  71.  
  72.     template<typename T>
  73.     using is_fourth_overload = std::bool_constant<!has_non_member_to_string<T>::value && !has_non_member_to_string<T>::value &&
  74.         !has_member_to_string<T>::value && !is_convertible_to_string<T>::value>;
  75.  
  76.     // first overload is for objects which are implicity convertible to std::string
  77.     template<typename T>
  78.     auto as_string(T&& object) -> std::enable_if_t<is_first_overload<T>::value, std::string> {
  79.         return std::forward<T>(object);
  80.     }
  81.  
  82.     // second overload is for objects with member function 'to_string'
  83.     template<typename T>
  84.     auto as_string(T&& object) -> std::enable_if_t<is_second_overload<T>::value, std::string> {
  85.         return std::forward<T>(object).to_string();
  86.     }
  87.  
  88.     // third overload is for objects with non-member function 'to_string' (std::to_string or found via ADL)
  89.     template<typename T>
  90.     auto as_string(T&& object) -> std::enable_if_t<is_third_overload<T>::value, std::string> {
  91.         using std::to_string;
  92.         return to_string(std::forward<T>(object));
  93.  
  94.     };
  95.  
  96.     // fourth overload is for objects with operator<< with std::ostream
  97.     template<typename T>
  98.     auto as_string(T&& object) -> std::enable_if_t<is_fourth_overload<T>::value, std::string> {
  99.         std::ostringstream stream;
  100.         stream << std::forward<T>(object);
  101.         return stream.str();
  102.  
  103.     }
  104.  
  105. }
  106.  
  107. template<typename T>
  108. std::string as_string(T&& value) {
  109.     return details::as_string(std::forward<T>(value));
  110. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement