-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathto.h
146 lines (131 loc) · 4.99 KB
/
to.h
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
#include <sstream>
#include "variadic.h"
namespace utl{
template<class StrLike>
struct is_string_like : std::integral_constant<bool,std::is_same<StrLike,std::string>::value || std::is_same<StrLike, char*>::value >{};
template<std::size_t N>
struct is_string_like<char[N]> : std::true_type{};
//case 1: integral or float -> string
template<class Dst,class Src>
inline auto To(Src const& src)
-> typename std::enable_if<(std::is_integral<Src>::value||std::is_floating_point<Src>::value)&&is_string_like<Dst>::value, std::string>::type {
return std::to_string(src);
}
// case 2: string -> integral or float
// string -> int
template<class Dst,class Src>
inline auto To(Src const& str)
->typename std::enable_if<is_string_like<Src>::value&&std::is_same<Dst,int>::value, int>::type{
return std::stoi(str);
}
// string -> unsigned int
template<class Dst,class Src>
inline auto To(Src const& str)
->typename std::enable_if<is_string_like<Src>::value&&std::is_same<Dst,unsigned int>::value, unsigned int>::type{
auto l = std::stol(str);
if(l>std::numeric_limits<unsigned int>::max() || l<std::numeric_limits<unsigned int>::min()){
throw std::out_of_range(str+" is greater than maximal uint or less than minimal uint");
}
return static_cast<unsigned int>(l);
}
// string -> long
template<class Dst,class Src>
inline auto To(Src const& str)
->typename std::enable_if<is_string_like<Src>::value&&std::is_same<Dst,long>::value, long>::type{
return std::stol(str);
}
// string -> unsigned long
template<class Dst,class Src>
inline auto To(Src const& str)
->typename std::enable_if<is_string_like<Src>::value&&std::is_same<Dst,unsigned long>::value, unsigned long>::type{
return std::stoul(str);
}
// string -> long long
template<class Dst,class Src>
inline auto To(Src const& str)
->typename std::enable_if<is_string_like<Src>::value&&std::is_same<Dst,long long>::value, long long>::type{
return std::stoll(str);
}
// string -> unsigned long long
template<class Dst,class Src>
inline auto To(Src const& str)
->typename std::enable_if<is_string_like<Src>::value&&std::is_same<Dst,unsigned long long>::value, unsigned long long>::type{
return std::stoull(str);
}
// string -> float
template<class Dst,class Src>
inline auto To(Src const& str)
->typename std::enable_if<is_string_like<Src>::value&&std::is_same<Dst,float>::value, float>::type{
return std::stof(str);
}
// string -> double
template<class Dst,class Src>
inline auto To(Src const& str)
->typename std::enable_if<is_string_like<Src>::value&&std::is_same<Dst,double>::value, double>::type{
return std::stod(str);
}
// string -> long double
template<class Dst,class Src>
inline auto To(Src const& str)
->typename std::enable_if<is_string_like<Src>::value&&std::is_same<Dst,long double>::value, long double>::type{
return std::stold(str);
}
// case 3: enum to integral or float
template<class Dst,class Src>
auto To(Src const& src)
-> typename std::enable_if<std::is_enum<Src>::value && (std::is_integral<Dst>::value
||std::is_floating_point<Dst>::value), Dst>::type {
using UT = typename std::underlying_type<Src>::type;
UT e = static_cast<UT>(src);
if(e>std::numeric_limits<Dst>::max()){
throw std::out_of_range("enum value="+std::to_string(e)+" is greater than maximal Dst type");
}
return static_cast<Dst>(e);
}
// case 4: integral to enum
template<class Dst, class Src>
inline auto To(Src const& src)
-> typename std::enable_if<std::is_integral<Src>::value && std::is_enum<Dst>::value, Dst>::type {
return static_cast<Dst>(src);
}
// case 5: Src can implicitly convert to Dst
template<class Dst, class Src>
inline auto To(Src&& src)
-> typename std::enable_if<std::is_convertible<Src,Dst>::value, Dst>::type {
return std::forward<Src>(src);
}
// case 6: concat srcs... to string
struct ToHook{
ToHook(std::ostringstream& oss_) : oss(oss_){}
template<class T>
void operator()(T const& val){
oss << To<std::string>(val);
}
std::ostringstream& oss;
};
template<class... Args>
auto To(Args&&... args)
-> typename std::enable_if<(sizeof...(Args)>1), std::string>::type{
std::ostringstream oss;
vparams(ToHook(oss), std::forward<Args>(args)...);
return oss.str();
}
// case 7: for T,if ostream& operator<<( ostream& os, T const&) has defined,
// not integral, not floating point and not string like
// then to<std::string> is enabled
template<class T>
struct is_out_streamable{
template<class U>
static auto test(U* ptr)->decltype( std::declval<std::ostream>() <<*ptr, std::true_type{});
template<class U>
static auto test(...)->std::false_type;
enum{ value = decltype(test<T>(nullptr)){}, };
};
template<class Dst, class Src>
auto To(Src const& src)
-> typename std::enable_if<is_out_streamable<Src>::value && not std::is_integral<Src>::value && not std::is_floating_point<Src>::value && not is_string_like<Src>::value && std::is_same<std::string,Dst>::value, std::string>::type{
std::ostringstream oss;
oss<<src;
return oss.str();
}
} // end of utl