summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2020-12-19 15:29:32 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2020-12-19 19:18:12 +0000
commit6ea6e77967e0656790f33db2c3e1b3f141e905a5 (patch)
treef48fddfb43ddfe8bd5f96d4664da3433d262b35a
parentDisable misc-no-recursion on Slice search functions (diff)
downloadicespider-6ea6e77967e0656790f33db2c3e1b3f141e905a5.tar.bz2
icespider-6ea6e77967e0656790f33db2c3e1b3f141e905a5.tar.xz
icespider-6ea6e77967e0656790f33db2c3e1b3f141e905a5.zip
Constexpr typename helpers
-rw-r--r--icespider/core/Jamfile.jam4
-rw-r--r--icespider/core/util-test.cpp12
-rw-r--r--icespider/core/util.h71
3 files changed, 86 insertions, 1 deletions
diff --git a/icespider/core/Jamfile.jam b/icespider/core/Jamfile.jam
index 15648b8..7b7bd19 100644
--- a/icespider/core/Jamfile.jam
+++ b/icespider/core/Jamfile.jam
@@ -2,9 +2,11 @@ lib adhocutil : : : : <include>/usr/include/adhocutil ;
lib slicer : : : : <include>/usr/include/slicer ;
lib stdc++fs ;
+obj util-test : util-test.cpp ;
+
obj routeOptions : routeOptions.ice : <toolset>tidy:<checker>none ;
lib icespider-core :
- [ glob *.cpp ]
+ [ glob *.cpp : *-test.cpp ]
routeOptions
:
<library>../common//icespider-common
diff --git a/icespider/core/util-test.cpp b/icespider/core/util-test.cpp
new file mode 100644
index 0000000..32a7c42
--- /dev/null
+++ b/icespider/core/util-test.cpp
@@ -0,0 +1,12 @@
+#include "util.h"
+
+namespace foo ::bar {
+ class really;
+}
+
+static_assert(type_names<int>::name() == "int");
+static_assert(type_names<int>::namespaces() == 0);
+static_assert(TypeName<int>::str() == "int");
+static_assert(type_names<foo::bar::really>::name() == "foo::bar::really");
+static_assert(type_names<foo::bar::really>::namespaces() == 2);
+static_assert(TypeName<foo::bar::really>::str() == "foo.bar.really");
diff --git a/icespider/core/util.h b/icespider/core/util.h
index 2089ce0..ca1350b 100644
--- a/icespider/core/util.h
+++ b/icespider/core/util.h
@@ -2,6 +2,8 @@
#define ICESPIDER_CORE_UTIL_H
#include <Ice/Optional.h>
+#include <array>
+#include <string_view>
namespace std::experimental::Ice {
template<typename T, typename TF>
@@ -37,4 +39,73 @@ orelse(const T & a, const T & b)
return b;
}
+template<typename T> struct type_names {
+ static constexpr auto
+ pf()
+ {
+ return std::string_view {&__PRETTY_FUNCTION__[0], sizeof(__PRETTY_FUNCTION__)};
+ }
+
+ static constexpr auto
+ name()
+ {
+ const std::string_view with_T {"T = "};
+ const auto start {pf().find(with_T) + with_T.length()};
+ const auto end {pf().find(']', start)};
+ return pf().substr(start, end - start);
+ }
+
+ static constexpr auto
+ namespaces()
+ {
+ auto ns {0U};
+ for (const auto & c : name()) {
+ // cppcheck-suppress useStlAlgorithm; (not constexpr)
+ ns += (c == ':') ? 1 : 0;
+ }
+ return ns / 2;
+ }
+
+ using char_type = typename decltype(name())::value_type;
+};
+
+template<typename T> class TypeName : type_names<T> {
+public:
+ constexpr static inline auto
+ str()
+ {
+ return std::string_view {buf.data(), buf.size() - 1};
+ }
+
+ constexpr static inline auto
+ c_str()
+ {
+ return buf.data();
+ }
+
+private:
+ using tn = type_names<T>;
+
+ constexpr static auto buf {[]() {
+ std::array<typename tn::char_type, tn::name().length() - tn::namespaces() + 1> buf {};
+ auto out {buf.begin()};
+ auto cln {false};
+ for (const auto & in : tn::name()) {
+ if (in == ':') {
+ if (cln) {
+ *out++ = '.';
+ }
+ else {
+ cln = true;
+ }
+ }
+ else {
+ *out++ = in;
+ cln = false;
+ }
+ }
+ return buf;
+ }()};
+};
+
#endif