0

Introduction:I want the explicit sepiaclization to show the longest string, I thought it be "Carmelo Anthony", but the result is "Jordan". I know the general template version is used instead of the explicit one. So it just compare the point's value(address value),right ? But How could I see the "Carmelo Anthony"? Thank you for answering my first post !

#include <iostream>
#include <cstring>     //for strlen()

template <class T>     //general template
T maxn (T arr[], int n);
template <> char * maxn<char *>(char * arr[], int n);    //explicit specialization

int main()
{
    using namespace std;
    int intArr[6] = {1, 2, 34, 6, 9, 10};
    double douArr[4] = {2.34, 90.6, -83.872, -0.23};
    const char * arr[5] = 
    {
        "Hello World",
        "Kobe Bryant",
        "Lebron James",
        "Carmelo Anthony",
        "Jordan"            
    };
    std::cout << maxn (intArr, 6) << std::endl;
    std::cout << maxn (douArr, 4) << std::endl;
    std::cout << maxn (arr, 5) << std::endl;
    return 0;
}

template <class T>
T maxn (T arr[], int n)
{
    T maxValue =  arr[0];
    for (int i = 1; i < n; i++)
    {
        maxValue = maxValue > arr[i] ? maxValue:arr[i];
    }
    return maxValue;
}

template <> char * maxn<char *>(char * arr[], int n)
{
    char * p= arr[0];   //pointer p points to the present longest string
    for (int i = 1; i < n; i++)
    {
        p = strlen (arr[i]) > strlen (p) ? arr[i] : p;
    }
    return p;
}
Marvin Dev
  • 73
  • 1
  • 1
  • 7

2 Answers2

1

As @PaulMcKenzie suggests, the problem is the missing const. To be a little more detailed, your template specialization is for arrays of pointers to non-const (ie, mutable) char. This tells the compiler that you might change the strings that are being passed in. However, you pass in an array of const char *, ie immutable strings. The compiler won't let you call a function that might mutate the data on const data, therefore it will not use your specialization unless you add const.

Nicu Stiurca
  • 8,747
  • 8
  • 40
  • 48
0

As an addition to the previous answer, you could specialize both const char * and char * by supplying a simple helper function that both versions will call:

#include <iostream>
#include <cstring>     //for strlen()

template <class T>     //general template
T maxn(T arr[], int n);
template <> const char * maxn<const char *>(const char * arr[], int n);    //explicit specialization
template <> char * maxn<char *>(char * arr[], int n);

int main()
{
    using namespace std;
    int intArr[6] = { 1, 2, 34, 6, 9, 10 };
    double douArr[4] = { 2.34, 90.6, -83.872, -0.23 };
    const char * arr[5] =
    {
        "Hello World",
        "Kobe Bryant",
        "Lebron James",
        "Carmelo Anthony",
        "Jordan"
    };

    char * arr2[5];
    for (int i = 0; i < 5; ++i)
    {
        arr2[i] = new char[strlen(arr[i]) + 1];
        strcpy(arr2[i], arr[i]);
    }

    std::cout << maxn(intArr, 6) << std::endl;
    std::cout << maxn(douArr, 4) << std::endl;
    std::cout << maxn(arr, 5) << std::endl;
    std::cout << maxn(arr2, 5) << std::endl;
    return 0;
}

template <class T>
T maxn(T arr[], int n)
{
    T maxValue = arr[0];
    for (int i = 1; i < n; i++)
    {
        maxValue = maxValue > arr[i] ? maxValue : arr[i];
    }
    return maxValue;
}

template<typename T> 
T* charHelper(T *arr[], int n)
{
    T* p = arr[0];
    for (int i = 1; i < n; i++)
    {
        p = strlen(arr[i]) > strlen(p) ? arr[i] : p;
    }
    return p;
}

template <> char * maxn<char *>(char * arr[], int n)
{ return charHelper<char>(arr, n); }

template <> const char * maxn<const char *>(const char * arr[], int n)
{ return charHelper<const char>(arr, n); }

Output:

34
90.6
Carmelo Anthony
Carmelo Anthony

Disregard the obvious memory leak in the main function for now.

Note that for the arr version, the const char* specialization is called, while for the arr2 version, the char * version is called.

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
  • OK ! I was wondering the memory leak when reading your code. Thank you,again. – Marvin Dev Sep 04 '14 at 06:41
  • @Mayboy You actually _don't_ need to specialize both `const char *` and `char *`. You can pass a (non-`const`) `char *` argument to a function taking `const char *` parameter. The `const` when present in the parameter list basically says "I promise not to change this data", and it doesn't matter if the argument was mutable or not to begin with. – Nicu Stiurca Sep 04 '14 at 16:31
  • @SchighSchagh Yes, you are right. I was also aware of that yesterday, but forgot to update it. template : template T* maxn(T *arr[], int n) { T* p = arr[0]; for (int i = 1; i < n; i++) { p = strlen(arr[i]) > strlen(p) ? arr[i] : p; } return p; } So, no need to specialize both const char * and char *, right ? – Marvin Dev Sep 04 '14 at 23:32