Why I can't pass string literals to const char* const& in this specialized function template
06:24 09 Feb 2022

Why pass a string literal to const char* const& in a specialized function template is illegal, while to const char* is legal?

Here's the thing. There are two excercises about template specialization in C++ Primer:

Exercise 16.63: Define a function template to count the number of occurrences of a given value in a vector. Test your program by passing it a vector of doubles, a vector of ints, and a vector of strings.

Exercise 16.64: Write a specialized version of the template from the previous exercise to handle vector and a program that uses this specialization.

The code below is my answer, the compile error appears when I pass the string literal to this specialized count function.

// Count the number of occurrences of a given value in a vector
template 
std::size_t count(const std::vector& vec, const T& value)
{
    std::size_t i = 0;
    for (const auto& v : vec) {
        if (v == value)
            ++i;
    }
    return i;
}

// A specialized version where T = const char*
template <>
std::size_t count(const std::vector& vec, const char* const& value)
{
    std::size_t i = 0;
    for (const auto& v : vec) {
        if (!strcmp(v, value))
            ++i;
    }
    return i;
}

int main()
{
    std::vector sVec{ "cpp", "primer", "cpp", "fifth", "edition", "Cpp", "cpp" };
    
    // Error message: no instance of function template "count" matches the argument list, 
    // argument types are: (std::vector>, const char [4])
    std::cout << count(sVec, "cpp") << std::endl;

    return 0;
}

Besides, it's perfectly ok to pass a string literal to const char* const& in a non-template function, which makes me confused.

void test(const char* const& str)
{
    std::cout << str << std::endl;
}

int main()
{
    test("cpp"); // Prints "cpp" as expected
    return 0;
}
c++ pointers string-literals