Question

Not even sure what the right terminology for this situation is. If I knew it then I probably would have found the answer.

I have a templatized function that looks like

template<typename T> void write(Buffer& b, const T& value);

There is no generic implementations of this, only explicit specializations. E.g.

template<> void write<int>(Buffer& b, const int& value) { ... }
template<> void write<const char *>(Buffer& b, const char * const & value) { ... }

So far so good. But of course when I call as write(buffer, "hello") I get a link error complaining

undefined reference to `void write<char [6]>(Buffer&, char const (&) [6])'

This error makes sense to me. But what I cannot figure out is how to declare a specialization for this. All I want such a specialization to do is cast the char[] argument to (const char*) and call that existing specialization. But I cannot figure out how to do this.

For the specific example I can do

template<size_t N> void write<char[6]>(Buffer& b, char const (&value) [6])

but it's obviously not acceptable to define one of these for every possible length string constant. But I've tried the following, some of which are just grasping for straws, and none of which work.

template<size_t N> void write<char const[N]>(Buffer& ob, char const (&value) [N])
template<size_t N> template<> void write<char const[N]>(Buffer& ob, char const (&value) [N])
template<> template<size_t N> void write<char const[N]>(Buffer& ob, char const (&value) [N])
template<template<size_t N>> void write<char const[N]>(Buffer& ob, char const (&value) [N])

What's the proper incantation? I'm using GCC 4.7.3 x86_64.

Was it helpful?

Solution 2

You can't do partial specialization of template functions. See this explanation for how to do a level of indirection to a function in a templated class in order to get around this limitation.

In this simple case you could also get by with a non-template write that invokes the template one:

void write(Buffer &b), const char *v)
{
    write<const char *>(b, v);
}

This effectively hides the cast that would have worked with your template function in an inline function.

OTHER TIPS

If it is OK, not to specify the argument type when calling the write() function with a character array (or to use char const* in these cases rather than, e.g., char[6]), the way to implement this is to use an overload to deal with char const*:

void write(Buffer& ob, char const* value) {
    write<char const*>(ob, value);
}

This function is preferred over the template instantiations and can, thus, be used to suitably delegate the processing for string literals (or C-strings in general, actually).

If it is necessary to get the correct type passed, the only way which would work is to not specialize the actual function template but, instead, to immediately delegate a struct with a suitable member function and to partially specialize this struct to deal with arrays: you cannot partially specialize a function template, i.e., the following is illegal:

template <int N>
void write<char const[N]>(Buffer& ob, char const (&value)[N]); // ERROR

... but it can be simulated by partially specializing a struct instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top