Template partial specialization

Hi guys, what is wrong with my code ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template <class T,int n>
T sum(T a){
	return a;
}


template <double,int n>
double sum(double a){
	return a;
}


template <int,int n>
int sum(int a){
	return a;
}


I'm trying to do 2 partial specializations, one with the template argument int, and the other one with double.
I get the following error:
error C2993: 'double' : illegal type for non-type template parameter '__formal'
Last edited on
I don't have equipment here to test, but for the specializations I think you need to remove the template parameters you are specializing from the template portion and add a <> including the specialized type names.

Terrible explanation, so here is my untested guess:
1
2
3
4
5
6
7
8
9
template <class T,int n>
T sum(T a){
	return a;
}

template <int n>
double sum<double, n>(double a){
	return a;
}
Tested, i get following error:
'sum' : illegal use of explicit template arguments

It's strange that the int specialization compiles without problems.
Last edited on
Bumpy, this really gives me trouble.
http://en.cppreference.com/w/cpp/language/template_parameters

In the Non-type template parameter section:

type is one of the following types (optionally cv-qualified, the qualifiers are ignored):

std::nullptr_t (since C++11);
integral type;
lvalue reference type (to object or to function);
pointer type (to object or to function);
pointer to member type (to member object or to member function);
enumeration type.


So do you just need to make it a template type parameter ? I haven't tested this:

1
2
3
4
template <int n,  typename T = double>
T sum(T a){
	return a;
}


Edit: It doesn't force the type to double, but you could do a static_assert with a type trait to see that it is.
Last edited on
Thanks for helping out.

I get this error:
error C2995: 'T sum(T)' : function template has already been defined
Your code looks more like defining default template parameters, which should be another thing.

Also, if you look in the first post, I'm not trying to specialize the non-type parameter(int n), but the type parameter(class T)
Last edited on
Also, if you look in the first post, I'm not trying to specialize the non-type parameter(int n), but the type parameter(class T)


Yes, but you had this:

template <double,int n>

The double is being interpreted as a non type parameter, but it must be one of the types that I had shown above. Otherwise a type parameter which is what my small example did.

It's strange that the int specialization compiles without problems.


This is because an integral type can be a non type parameter.

function template has already been defined


Do you have both of these?

1
2
3
4
5
6
7
8
9
template <double,int n>
double sum(double a){
	return a;
}

template <int n,  typename T = double>
T sum(T a){
	return a;
}

I think I understand what you mean.

This is what I'm compiling when I get the C2995 error:

1
2
3
4
5
6
7
8
9
10
template <class T,int n>
T sum(T a){
	return a;
}


template <typename T = double  ,int n>
T sum(T a){
	return a;
}
A function template can be explicitly (fully) specialized;
however, unlike a class template, a function template can't be partially specialized.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <type_traits>

template < typename T, int UNUSED > struct A
{ static T sum( T a ) { std::cout << "non-specialised\n" ; return a ; }  } ;

template < int UNUSED > struct A< double, UNUSED >
{ static double sum( double a ) { std::cout << "partial specialisation for double\n" ; return a ; }  } ;

template < int UNUSED, typename T > T sum( T a ) { return A<T,UNUSED>::sum(a) ; }

int main()
{
    auto i = sum<0>(23) ; // non-specialised
    static_assert( std::is_same< decltype(i), int >::value, "expected int" ) ;

    auto d = sum<0>( 23.0 ) ; // partial specialisation for double
    static_assert( std::is_same< decltype(d), double >::value, "expected double" ) ;
}

http://coliru.stacked-crooked.com/a/a412573ccfaa1737
http://rextester.com/JFNJZ24248

It's okay to overload function templates. Overload resolution considers all base templates equally and so it works as you would naturally expect from your experience with normal C++ function overloading: Whatever templates are visible are considered for overload resolution, and the compiler simply picks the best match.

It's a lot less intuitive to specialize function templates. For one thing, you can't partially specialize them -- pretty much just because the language says you can't. For another thing, function template specializations don't overload. This means that any specializations you write will not affect which template gets used, which runs counter to what most people would intuitively expect. After all, if you had written a nontemplate function with the identical signature instead of a function template specialization, the nontemplate function would always be selected because it's always considered to be a better match than a template.

If you're writing a function template, prefer to write it as a single function template that should never be specialized or overloaded, and implement the function template entirely in terms of a class template. This is the proverbial level of indirection that steers you well clear of the limitations and dark corners of function templates. This way, programmers using your template will be able to partially specialize and explicitly specialize the class template to their heart's content without affecting the expected operation of the function template. This avoids both the limitation that function templates can't be partially specialized, and the sometimes surprising effect that function template specializations don't overload. Problem solved.

If you're using someone else's plain old function template (one that's not implemented in terms of a class template as suggested above), and you want to write your own special-case version that should participate in overloading, don't make it a specialization; just make it an overloaded function with the same signature.

Sutter 'Why Not Specialize Function Templates?' http://www.gotw.ca/publications/mill17.htm

You may want to read the entire article.
Hi,

The default parameter must be at the end.

In your OP you had 3 specialisations, the first one could evaluate to the same as what you were trying to achieve with the second one.

Does this work?

1
2
3
4
5
6
7
8
9
template <int n,  typename T = double>
T sum(T a){
	return a;
}

template <int,int n>
int sum(int a){
	return a;
}


Also you aren't using the n parameter, is there a need to have it?

When I read up about that C2995 error, it talks a lot about circular includes, lack of include guards and template code in cpp files, hopefully you aren't doing any of those things?
Thanks guys. JLBorges, that's a good read.

TIM, that code works. I know both specializations in the first post do the same thing, and int n is also not used. This code is just for testing the syntax.

Just thought these might be relevant as well, but one should be very well advised to follow JLBorges advice :+)

https://isocpp.org/wiki/faq/templates#fn-templates-explicit-calls

One could write one template, then force the type to be used when the function is called.

Although that is not really a specialisation, but then there are these:

https://isocpp.org/wiki/faq/templates#template-specialization
https://isocpp.org/wiki/faq/templates#template-specialization-example
Topic archived. No new replies allowed.