Steven Lu Steven Lu - 1 month ago 16
C++ Question

Concatenate compile-time strings in a template at compile time?

Currently I 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'm forced to allocate a string to perform the concatenation.

This is all happening at compile time, i.e. I intend to get the string
"int****"
when I reference
typename_struct<int****>::name()
. (Do assume that I have declared a corresponding specialization for
int
which returns
"int"
)

As the code is written now, does the compiler do the concatenation with std::string during compile time only? (I would be okay with that) Or does such a call result in 4 std::string based concatenations at runtime? (I would not be okay with that)

pdw pdw
Answer

You could 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;
}