Search code examples
c++templatesexplicit-specialization

Why can't I call the C++ explicit specialization version of following code?


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;
}

Solution

  • 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.