5

I want to be able to specialize based on a constant c style string. The problem is that when I call my templatized function the type is const char[N] where 'N' is the size of the string +1 (null character). How can I specialize for all c-style strings?

The following code displays the problem. You can see the specialization for const char [15] gets matched for "const char [15]" but for "const char[5]" it goes to Generic.

Is there any way to do this?

template <typename T>
struct Test {
  static const char* type() { return "Generic"; }
};

template <>
struct Test<const char*> {
  static const char* type() { return "const char*"; }
};

template <>
struct Test<const char[]> {
  static const char* type() { return "const char[]"; }
};

template <>
struct Test<const char[15]> {
  static const char* type() { return "const char[15]"; }
};

template <>
struct Test<char*> {
  static const char* type() { return "char*"; }
};

template <>
struct Test<char[]> {
  static const char* type() { return "char[]"; }
};

template <typename T>
void PrintType(const T& expected) {
  std::cerr << expected << " type " << Test<T>::type() << std::endl;
}
int main(int argc, char* argv[]) {
  const char* tmp = "const char*";
  PrintType(tmp);
  PrintType("const char[]");
  PrintType("const char[15]");
  PrintType("const char[5]");
}

output when run in Windows 7 - VS 2008

const char* type const char*
const char[] type Generic
const char[15] type const char[15]
const char[5] type Generic

2 Answers 2

13

A specialization for any array of chars is:

template< std::size_t N >
struct Test< const char[N] > { ... };

However you can no longer return a char* from type(), unless you write more metafunctions to turn a non-type template parameter into its textual representation.

Sign up to request clarification or add additional context in comments.

1 Comment

The char* returned from type() was only for debugging purposes. I could have just outputted 1,2,3,4... as well. This was a made up example of my problem. Thanks.
1

Try this:

#include <cstdio>
#include <string>

template<class T>
void f2(const T& s) // Handle all kinds of string objects
{ std::printf("string object: %s\n", s.c_str()); }

void f2(const char* s) // Handle const char*
{ std::printf("const char*: %s\n", s); }

// ----------------------------------------------------------------------------

template<size_t N>
void f(const char(&s)[N]) // Handle const char array
{ std::printf("const char[%zu]: %s\n", N, s); }

template<size_t N>
void f(char(&s)[N]) // Handle char array
{ std::printf("char[%zu]: %s\n", N, s); }

template<class T>
inline void f(T&& s) // Handle other cases
{ f2(std::forward<T>(s)); }

int main() {
  std::string stringObj     = "some kind of string object ...";
  char charArr[]            = "char array";
  const char constCharArr[] = "const char array";
  const char* constCharPtr  = "const char pointer";

  f(stringObj);
  f(charArr);
  f(constCharArr);
  f(constCharPtr);
  //f("const char array");
}

Output:

string object: some kind of string object ...
char[11]: char array
const char[17]: const char array
const char*: const char pointer

Explanation

f() has two kinds of overloads: One for char arrays and one for "everything else".

f2() handles the "everything else" case.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.