Explicit Specialization error.

Hi all. I have an exercise where I need to declare an explicit specialization of a template to accept an array of pointers to strings, then use the specialization to return the pointer to the largest string. Here's the error I'm getting:

C:\Users\Raezzor\Desktop\Coding Projects\8.6\main.cpp|10|error: template-id 'maxn<const char*>' for 'char* maxn(const char**, int)' does not match any template declaration|
C:\Users\Raezzor\Desktop\Coding Projects\8.6\main.cpp|49|error: template-id 'maxn<const char*>' for 'char* maxn(const char**, int)' does not match any template declaration|
||=== Build finished: 2 errors, 4 warnings ===|


And here's my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <cstring>

using std::cout;
using std::endl;

template <typename T>
T maxn(const T arr[],const int size);       // template prototype for the maxn function

template <> char* maxn<const char*>(const char* cp_arr[],const int size);  // specialization prototype for the array of pointers

int main()
{
    int n_arr[] = {1, 2, 3, 4, 5, 6};
    double d_arr[] = {1.1, 2.2, 3.3, 4.4};
    char* cp_arr[] = {"Hi!", "A string!", "This is a bigger string1!", "This is a bigger string2!"};

    int n_max = maxn(n_arr, 6);
    double d_max = maxn(d_arr, 4);
    char* cp_max = maxn(cp_arr, 4);

    cout << "Int max is:"
         << n_max
         << endl
         << "Double max is:"
         << d_max
         << endl
         << "Biggest string is:"
         << *cp_max
         << endl;

    return 0;
}

template <typename T>
T maxn(const T arr[], const int size)
{
    T max = arr[0];

    for (int i = 1; i < size; i++)
    {
        if (max < arr[i])
            max = arr[i];
    }

    return max;
}

template <> char* maxn<const char*>(const char * cp_arr[],const int size)
{
    char* cp_max = cp_arr[0];
    for (int i = 1; i < size; i++)
    {
        if (strlen(cp_max) < strlen(cp_array[i]))
            cp_max = cp_arr[i];
    }

    return cp_max;
}


The book I'm using does a decent job of explaining what specializations are and all, so I'm guessing my error lies somewhere in the way I'm declaring the specialization itself or having to do with the way I'm using the pointers. Anyway, any help is appreciated.
Last edited on
Templates can't be declared and then defined later; the compiler needs to know every inch of them for them to work. They're essentially macros, and it doesn't make sense to use a macro if you don't yet know what it expands to.
That's odd, since that's opposite of the way the book shows using a template prototype, then defining the template after main just like regular functions.
What's the name of the book?

Edit: I think it may be possible within the same cpp file to do that, but it is certainly not possible afaik across multiple cpp files - the whole definition of the template is generally in the common header included by all cpp files.
Last edited on
C++ Primer Plus 6th ed. by Stephen Prata. I have completed a previous exercise using a simple function template and used a prototype in that one. It's just the specialization that's giving me trouble with this one.
You should simply replace T with the type that you want.
1
2
3
4
5
6
template <typename T>
T maxn(const T arr[],const int size);       // template prototype for the maxn function

//T=char*
template<>
char* maxn( char * const arr[], const int size );
T is a pointer, so the pointer should be constant.

However, your compiler should have warning you that "This is a bigger string2!" is a const char* and its conversion to char* is deprecated.


> but it is certainly not possible afaik across multiple cpp files
It is possible through explicit template instantiation. However you don't have the T=anything, but just the type you define it for.
Last edited on
Ya, I did get those warning, I just edited them out to decrease the size of the post a bit heh.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <cstring>

using std::cout;
using std::endl;

template <typename T>
T maxn(const T arr[],const int size);       // template prototype for the maxn function

template <> char* maxn(char* cp_arr[],const int size);  // specialization prototype for the array of pointers

int main()
{
    int n_arr[] = {1, 2, 3, 4, 5, 6};
    double d_arr[] = {1.1, 2.2, 3.3, 4.4};
    char* cp_arr[] = {"Hi!", "A string!", "This is a bigger string1!", "This is a bigger string2!"};

    int n_max = maxn(n_arr, 6);
    double d_max = maxn(d_arr, 4);
    char* cp_max = maxn(cp_arr, 4);

    cout << "Int max is:"
         << n_max
         << endl
         << "Double max is:"
         << d_max
         << endl
         << "Biggest string is:"
         << *cp_max
         << endl;

    return 0;
}

template <typename T>
T maxn(const T arr[], const int size)
{
    T max = arr[0];

    for (int i = 1; i < size; i++)
    {
        if (max < arr[i])
            max = arr[i];
    }

    return max;
}

template <> char* maxn(char* cp_arr[],const int size)
{
    char* cp_max = cp_arr[0];
    for (int i = 1; i < size; i++)
    {
        if (strlen(cp_max) < strlen(cp_arr[i]))
            cp_max = cp_array[i];
    }

    return cp_max;
}


That gives me the exact same errors.

C:\Users\Raezzor\Desktop\Coding Projects\8.6\main.cpp|10|error: template-id 'maxn<>' for 'char* maxn(char**, int)' does not match any template declaration|
C:\Users\Raezzor\Desktop\Coding Projects\8.6\main.cpp|49|error: template-id 'maxn<>' for 'char* maxn(char**, int)' does not match any template declaration|


Edit: AHh nm, added the const properly on the array and it works. My bad. Thanks! But wait, that confuses me more. The type for the specialization was char*, so why doesn't const char* cp_arr[] work while char* const cp_arr[] does? What I was trying to do was pass an array of char pointers to the specialized function as consts so the function can't change any of them.
Last edited on
Well, I got rid of the deprecation errors by simply creating the strings individually then assigning them to the array of pointers. Prolly a better way to do that, but my head hurts atm. Also the output for *cp_max was a single letter so I removed the dereference operator and it worked fine. Man, working with c-style strings makes me appreciate the string class more.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <cstring>

using std::cout;
using std::endl;

template <typename T>
T maxn(T arr[], int size);       // template prototype for the maxn function

template <> char* maxn<char*>(char* cp_arr[], int size);  // specialization prototype for the array of pointers

int main()
{
    int n_arr[] = {1, 2, 3, 4, 5, 6};
    double d_arr[] = {1.1, 2.2, 3.3, 4.4};
    char cp1[] = "Hi!";
    char cp2[] = "A string!";
    char cp3[] = "This is a bigger string1!";
    char cp4[] = "This is a bigger string2!";
    char* cp_arr[] = {cp1, cp2, cp3, cp4};

    int n_max = maxn(n_arr, 6);
    double d_max = maxn(d_arr, 4);
    char* cp_max = maxn(cp_arr, 4);

    cout << "Int max is:"
         << n_max
         << endl
         << "Double max is:"
         << d_max
         << endl
         << "Biggest string is:"
         << cp_max
         << endl;

    return 0;
}

template <typename T>
T maxn(T arr[], int size)
{
    T max = arr[0];

    for (int i = 1; i < size; i++)
    {
        if (max < arr[i])
            max = arr[i];
    }

    return max;
}

template <> char* maxn<char*>(char* cp_arr[], int size)
{
    char* cp_max = cp_arr[0];
    for (int i = 1; i < size; i++)
    {
        if (strlen(cp_max) < strlen(cp_arr[i]))
            cp_max = cp_arr[i];
    }

    return cp_max;
}
"C++ Primer Plus" is a very, very bad book. "C++ Primer" is much, much better. This explains why the example in the book was wrong.

Also, is that your working code or is there still an issue?
Hmm, that's the first I heard of the Primer Plus being bad. What's so wrong with it? I'm not sure what example you are referring to in the book being wrong. All this code was written by me.

And ya, I took out all the consts since it wasn't really necessary. I'm going to re-read the sections on templates and specializations and re-add the consts once I get a better grasp of just what's going on with them.
Last edited on
Well, the code builds fine for me with both VC++ 2008 and GCC

Well, it's a templated function, rather than a class, so I guess that the compiler doesn't have to worry about storage up front.

I have to admit that I use templated classes a lot more than functions, so have always defined my templated function before use.

Andy
Last edited on
Raezzor wrote:
Hmm, that's the first I heard of the Primer Plus being bad. What's so wrong with it?
Read http://accu.org/index.php?module=bookreviews&func=search&rid=1744 (taken from http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list ) The example I refer to is the bad example it sets for you of declaring templates first and then defining them later.
On what grounds is that the definitive c++ booklist??
Last edited on
I had to buy that book for my C++/Java class. I very much agree with that review that it had no structure. It seemed like the author just kind of wrote stuff in some order as they thought about it and never actually bothered to organize.
Wow, it seemed like a good book to me, but then this isn't my first time tackling C++ either. I'll check out that Primer that you mentioned LB. Guess that's what I get for listening to the reviews on Amazon instead of checking on these boards first. :)

Edit: still not sure why what I wrote was bad though. I mean, we use function prototypes all the time. And all this is is a function template prototype.
Last edited on
Garbage tastes amazing if all you've ever known is dirt.
> The type for the specialization was char*, so why doesn't const char* cp_arr[] work while char* const cp_arr[] does?

1
2
3
4
5
6
7
char *ptr; //a pointer

const char *ptr = "hello"; //a pointer to a const object
*ptr = 'H'; //illegal

char * const ptr = new char[size]; //a constant pointer
ptr = NULL; //illegal 


Your original prototype
1
2
template <typename T>
T maxn(const T arr[],const int size);
If you say that T is a pointer, then the function returns a pointer and ask for an array of constant pointers.

What you tried
1
2
template <> 
char* maxn<const char*>(const char* cp_arr[],const int size);
It returns a pointer, but it ask for an array of pointer to const objects.
Ahhh right. Makes sense now. Thanks Ne555.
Topic archived. No new replies allowed.