Combine compile time strings in a template at compile time?

I currently have:

template <typename T> struct typename_struct<T*> { static char const* name() { return (std::string(typename_struct<T>::name()) + "*").c_str(); } }; 

I wonder if I can avoid the whole bit where I have to select a string to perform concatenation.

This happens at compile time, i.e. I intend to get the string "int****" when I refer to typename_struct<int****>::name() . (Suppose I declared a specialization for int that returns "int" )

Once the code is written now, does the compiler concatenate with std :: string only at compile time? (This will be all right) Or, such a call leads to concatenations based on

+5
c ++ string c ++ 11 templates template-meta-programming
source share
3 answers

You can use something like this. Everything happens at compile time. Specialize base_typename_struct to define your primitive types.

 template <const char* str, int len, char... suffix> struct append { static constexpr const char* value() { return append<str, len-1, str[len-1], suffix...>::value(); } }; template <const char* str, char... suffix> struct append<str, 0, suffix...> { static const char value_str[]; static constexpr const char* value() { return value_str; } }; template <const char* str, char... suffix> const char append<str, 0, suffix...>::value_str[] = { suffix..., 0 }; template <typename T> struct base_typename_struct; template <> struct base_typename_struct<int> { static constexpr const char name[] = "int"; }; template <typename T, char... suffix> struct typename_struct { typedef base_typename_struct<T> base; static const char* name() { return append<base::name, sizeof(base::name)-1, suffix...>::value(); } }; template <typename T, char... suffix> struct typename_struct<T*, suffix...>: public typename_struct<T, '*', suffix...> { }; int main() { cout << typename_struct<int****>::name() << endl; } 
+5
source share

An alternative way without using recursive patterns (but requires C ++ 14):

 #include <utility> template<int...I> using is = std::integer_sequence<int,I...>; template<int N> using make_is = std::make_integer_sequence<int,N>; constexpr auto size(const char*s) { int i = 0; while(*s!=0){++i;++s;} return i; } template<const char*, typename, const char*, typename> struct concat_impl; template<const char* S1, int... I1, const char* S2, int... I2> struct concat_impl<S1, is<I1...>, S2, is<I2...>> { static constexpr const char value[] { S1[I1]..., S2[I2]..., 0 }; }; template<const char* S1, const char* S2> constexpr auto concat { concat_impl<S1, make_is<size(S1)>, S2, make_is<size(S2)>>::value }; 

Example:

 constexpr const char a[] = "int"; constexpr const char c[] = "**"; #include <iostream> int main() { std::cout << concat<a,b> << '\n'; } 

append characters per line can also be implemented as follows, replacing the second parameter const char* with char...

+3
source share

I'm not sure what you are looking for, but I think you are interested in a combination of typeid and name-demangling (which compiler are you using?)

In gcc, it will be something like

 #include<iostream> #include <string> #include <typeinfo> #include <cstdlib> #include <memory> #include <cxxabi.h> using namespace std; std::string demangle(const char* name) { int status = -4; // some arbitrary value to eliminate the compiler warning // enable c++11 by passing the flag -std=c++11 to g++ std::unique_ptr<char, void(*)(void*)> res { abi::__cxa_demangle(name, NULL, NULL, &status), std::free }; return (status==0) ? res.get() : name ; } template <typename T> struct typename_struct { static std::string name() { std::string typeName = typeid(T).name(); return demangle(typeName.c_str()); } }; int main(){ cout << typename_struct<int****>::name(); // Prints "int****" return 0; } 

http://ideone.com/nLsFF0

Sources: fooobar.com/questions/62549 / ...

As for your question: this is not a constexpr construct, so the evaluation is performed at run time, although the template parameters and code are created at compile time.

Using templates does not mean that every instruction contained therein will be executed and allowed at compile time.

I believe that during compilation you cannot reach this chain of things, since it uses deactivation functions (ABI-specific). If I misinterpret your question, please let me know.

0
source share

All Articles