|
15 | 15 | #define PRETTY_FUNCTION __func__
|
16 | 16 | #endif
|
17 | 17 |
|
18 |
| -/** Very simple function for retrieving a signature containing the given template arguments. */ |
19 |
| -template<class... T> constexpr auto pretty(void) -> const char * { return PRETTY_FUNCTION; } |
20 |
| -/** Very simple function for retrieving a signature containing the given arguments' types. */ |
21 |
| -template<class... T> constexpr auto pretty(T &&... t) -> const char * { return PRETTY_FUNCTION; } |
22 |
| -/** Provides a filtered stream insertion operator to represent types as strings. */ |
23 |
| -template<class... T> struct Pretty { |
24 |
| - /** Same as top-level definitions of 'pretty'; returns compiler-defined function signature. */ |
25 |
| - static constexpr const char *pretty(void) { return PRETTY_FUNCTION; } |
26 |
| - operator std::string(void) const; |
27 |
| - /** Stream insertion operator; strips all but the type sequence from 'pretty'. */ |
28 |
| - template<class S> |
29 |
| - friend S& operator<<(S& s, Pretty const& p) { |
30 |
| - return s << std::string(p), s; |
| 18 | +template<class T> struct Pretty { |
| 19 | + static constexpr const char *pretty(void) { return PRETTY_FUNCTION; } |
| 20 | + operator std::string(void) const { |
| 21 | + using namespace std; |
| 22 | + string unknown = "(unknown)", |
| 23 | + with = "with T = ", |
| 24 | + orig = pretty(), lhs, rhs; |
| 25 | +#ifdef HAS_FUNCSIG |
| 26 | + lhs = "<", rhs = ">"; |
| 27 | +#elif defined HAS_PRETTY |
| 28 | + lhs = "{[", rhs = "]}"; |
| 29 | +#else |
| 30 | + return ""; |
| 31 | +#endif |
| 32 | + // Match the earliest opening and latest closing brackets |
| 33 | + auto p0 = orig.find_first_of(lhs), p1 = orig.find_last_of(rhs); |
| 34 | + if(p0 == string::npos || p1 == string::npos) return std::move(unknown); |
| 35 | + p0++; // Offset by the width of the opening character |
| 36 | + auto result = orig.substr(p0, p1-p0); |
| 37 | + if(orig.substr(p0, with.length()) == with) |
| 38 | + result = result.substr(with.length()); |
| 39 | + return result; |
31 | 40 | }
|
32 |
| - // Pedantic version - insertion into ostringstream& returns ostream&, etc. |
33 |
| - /*template<class S> |
34 |
| - friend auto operator<<(S &s, Pretty const& p) -> decltype(s << std::string()) { |
35 |
| - return s << std::string(p); |
36 |
| - }*/ |
| 41 | + template<class S> |
| 42 | + friend S& operator<<(S & s, Pretty const& p) |
| 43 | + { return s << std::string(p), s; } |
37 | 44 | };
|
38 | 45 |
|
39 |
| -/** Returns an instance of Pretty with the given types in the style of make_tuple. */ |
40 |
| -template<class... R> |
41 |
| -Pretty<R...> make_pretty(R &&... r) { return {}; } |
| 46 | +template<class... T> |
| 47 | +std::string pretty(void) { |
| 48 | + std::string strs[] = {std::string(Pretty<T>{})...}; |
| 49 | + std::string out, pfx = ""; |
| 50 | + for(auto const& str : strs) { |
| 51 | + out += pfx + str; |
| 52 | + pfx = ", "; |
| 53 | + } |
| 54 | + return out; |
| 55 | +} |
| 56 | +template<class... T> |
| 57 | +std::string pretty(T &&... t) { |
| 58 | + return pretty<T...>(); |
| 59 | +} |
42 | 60 |
|
43 | 61 | template<class T>
|
44 |
| -std::string prettyTrunc(void); |
| 62 | +std::string pretty_abbrev(void) { |
| 63 | + std::string s = Pretty<T>(), |
| 64 | + subs[][2] {{"std::", ""}, {"< <", "<<"}, {"> >", ">>"}}; |
| 65 | + std::size_t pos = 0; |
| 66 | + for(auto const& sub : subs) { |
| 67 | + pos = 0; |
| 68 | + while((pos = s.find(sub[0], pos)) != std::string::npos) { |
| 69 | + s.replace(pos, sub[0].length(), sub[1]); |
| 70 | + } |
| 71 | + } |
| 72 | + return s; |
| 73 | +} |
45 | 74 | template<class T>
|
46 |
| -std::string prettyTrunc(T && t); |
| 75 | +std::string pretty_abbrev(T && t) { |
| 76 | + return pretty_abbrev<T>(); |
| 77 | +} |
47 | 78 |
|
48 | 79 | #endif
|
0 commit comments