Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template specialization on functions

I'm playing around with template specialization, and I've found an issue I can't seem to solve; this is my code:

template<int length, typename T>
void test(T* array)
{
    ...
    test<length-1>(array);
}

template<typename T>
void test<0>(T* array)
{
    return;
}

So what I'm trying to do, is to pass the length, of what's to be processed in the template.

The problem is, that the compilation of this, well outputs forever:

a.cpp:83:43: error: template-id 'test<0>' in declaration of primary template
a.cpp: In function 'void test(T*) [with int length= -0x000000081, T = int]':
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= -0x000000080, T = int]'
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= -0x00000007f, T = int]'
a.cpp:77:9:   [ skipping 151 instantiation contexts ]
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= 28, T = int]'
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= 29, T = int]'
...
a.cpp: In function 'void test(T*) [with int length= -0x000000082, T = int]':
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= -0x000000081, T = int]'
a.cpp:77:9:   instantiated from 'void test(T*) [with int length= -0x000000080, T = int]'

Last two lines, is pretty much the same as the first ones.

To me it would seem, its not catching the specialization, hence:

a.cpp:83:43: error: template-id 'test<0>' in declaration of primary template

Am I correct?

And if I'm correct, I'm guessing it's the issue that partial template specialisation is not allowed for function templates, so what would be the solution then, making a struct, and using specialisation on that?

like image 317
Skeen Avatar asked Jul 08 '11 10:07

Skeen


People also ask

What is function template specialization?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization. A primary template is the template that is being specialized.

Why function template partial specialization is not allowed?

Function partial specialization is not yet allowed as per the standard. In the example, you are actually overloading & not specializing the max<T1,T2> function. In the case of a function templates, only full specialization is allowed by the C++ standard, -- excluding the compiler extensions!

What is the specialty of a template function give example?

Template in C++is a feature. We write code once and use it for any data type including user defined data types. For example, sort() can be written and used to sort any data type items. A class stack can be created that can be used as a stack of any data type.

What is explicit template specialization?

Explicit (full) specialization Allows customizing the template code for a given set of template arguments.


2 Answers

Partial specialization of function templates is not allowed. Herb Sutter explains why in his article "Why Not Specialize Function Templates?".

To work around this limitation you need to use class templates instead. You can then write a regular function template that uses that class template.

That specific error you're getting is because you forgot the second parameter in your specialization. If you this instead:

template<int length, typename T>
void test(T* array)
{
    //...
    test<length-1,T>(array);
}


template<typename T>
void test<0,T>(T* array)
{
    return;
}

GCC complains with the following:

error: function template partial specialization 'test<0, T>' is not allowed

like image 159
R. Martinho Fernandes Avatar answered Oct 12 '22 21:10

R. Martinho Fernandes


Functions cannot be partially specialized. To work around this, have your template function call a function in a class:

template<int length, typename T>
struct helper
{
    static void go(T* array)
    {
        ...
        helper<length-1, T>::go(array);
    }
};

template<typename T>
struct helper<0, T>
{
    static void go(T* array)
    {
        ...
    }
};

template<int length, typename T>
void test(T* array)
{
    ...
    helper<length, T>::go(array);
}
like image 29
Dark Falcon Avatar answered Oct 12 '22 22:10

Dark Falcon