attempting to specialize template function with non-type argument in C++

176 views Asked by At

I have a templated function, which takes an array reference as a parameter:

template<typename T, int arrSize>
void foo(T (&pArr)[arrSize]) {
    cout << "base template function" << endl;
}

I want to specialize this function for C-strings:

template<const char *, int arrSize>
void foo(const char * (&pArr)[arrSize]) {
    cout << "specialized template function" << endl;
}

I try to instantiate the base and the specialization:

int main(int argc, const char **argv) {
    float nums[] = {0.3, 0.2, 0.11};
    const char *words[] = {"word1", "word2"};
    foo(nums);
    foo(words);
}

But I only seem to get the base instantiation:

./foo
base template function
base template function

I have compiled this on a Mac using clang++ with -std=c++17.

2

There are 2 answers

0
user12002570 On BEST ANSWER

The problem is that the 2nd overloaded function template that you've provided has a non-type template parameter of type const char* that cannot be deduced from the function parameter. So to call this overloaded version we have to explicitly provide the template argument corresponding to this non-type parameter.

To solve this just remove the first non-type template parameter as shown below:

template<typename T, int arrSize>
void foo(T (&pArr)[arrSize]) {
    std::cout << "base template function" << std::endl;
}
//overload for C-strings
template< int arrSize>
void foo(const char (&pArr)[arrSize]) {
    std::cout << "single C-string overloaded version" << std::endl;
}
//overload for array of pointers to C-strings
template<std::size_t arrSize>
void foo(const char*(&pArr)[arrSize])
{
    std::cout<<" array of pointers to C-string version"<<std::endl;
}
int main(int argc, const char **argv) {
    float nums[] = {0.3, 0.2, 0.11};
    const char words[] = {"word1"};
    const char* wordPtrs[] = {"word1", "word2"};
    
    foo(nums); //calls base
    foo(words);//calls single C-string version
    foo(wordPtrs);//calls array of pointers to C-string version
}

Demo

Also note that function templates cannot be partially specialized but they can be fully specialized or they can be overloaded.

2
Red.Wave On

Try:

template<int arrSize>
void foo(const char * (&pArr)[arrSize]);

You were defining an overload expecting a non-deducible char const* non-type parameter.