Question

I am trying to write a template specialization for a function that returns the maximum value of an array of numeric values (general version) or the longest c-string of an array of c-strings (specialization). If I do not use const-ness, my function prototypes look like this

template <typename T>
T maxn(T* my_Tptr, unsigned int n);

template <>
char* maxn <char*> (char** my_cstrings, unsigned int n);

and my code compiles.

However, if I try to use const-ness, my function prototypes look like this,

template <typename T>
T maxn(const T* my_Tptr, unsigned int n);

template <>
char* maxn <char*> (const char** my_cstrings, unsigned int n);

my code does not compile, and the compiler (gcc) prints this error:

error: template-id 'maxn' for 'char* maxn(const char**, unsigned int)' does not match any template declaration.

Where am I going wrong?

Was it helpful?

Solution

The problem is in the constness. If you look closely const T* my_Tptr means my_Tptr is a pointer to const T. But const char** my_Tptr means Tptr is a pointer to pointer to const char. So the type moves from pointer to const T to pointer to pointer to const T. If you make it char* const* my_Tptr* then it will work, since then the type will be pointer to const char pointer. The specialization is pointer to const T*->pointer to const char*

OTHER TIPS

Not sure what is the whole logic behind it but if you change your template definition to say that you are expecting pointers that will help:

template <typename T>
T* maxn(const T** my_Tptr, unsigned int n);

template <>
char* maxn(const char** my_cstrings, unsigned int n);

You might provide several overloads for the char-case to resolve the issue:

#include <iostream>
#include <stdexcept>

template <typename T>
T maxn(const T* const data, unsigned int n) {
    throw std::logic_error("Failure");
}

const char* maxn(const char * const * data, unsigned int n) {
    return "Success";
}

inline const char* maxn(const char** data, unsigned int n) {
    return maxn(static_cast<const char * const *>(data), n);
}

inline const char* maxn(char* const * data, unsigned int n) {
    return maxn(static_cast<const char * const *>(data), n);
}

inline const char* maxn(char** data, unsigned int n) {
    return maxn(static_cast<const char * const *>(data), n);
}

int main() {
    const char* a[] = { "A", "B", "C" };
    std::cout << maxn((const char * const *)a, 3) << '\n';
    std::cout << maxn((const char **)a, 3) << '\n';
    std::cout << maxn((char * const *)a, 3) << '\n';
    std::cout << maxn((char**)a, 3) << '\n';
}

This compiles fine:

template <>
char* maxn(char* const* my_cstrings, unsigned int n);

It accepts a pointer to a const char pointer like specified in the base template.

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