C++ function template partial specialization?

c++ partial template specialization function
c++ function template specialization
partial template specialization c++
c++ template specialization member function
c template function specialization return type
template parameters not deducible in partial specialization
template specialization vs overloading
in instantiation of function template specialization

I know that the below code is a partial specialization of a class:

template <typename T1, typename T2> 
class MyClass { 
  … 
}; 


// partial specialization: both template parameters have same type 
template <typename T> 
class MyClass<T,T> { 
  … 
}; 

Also I know that C++ does not allow function template partial specialization (only full is allowed). But does my code mean that I have partially specialized my function template for one/same type arguments? Because it works for Microsoft Visual Studio 2010 Express! If no, then could you please explain the partial specialization concept?

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

template <typename T1, typename T2> 
inline T1 max (T1 const& a, T2 const& b) 
{ 
    return a < b ? b : a; 
} 

template <typename T> 
inline T const& max (T const& a, T const& b)
{
    return 10;
}


int main ()
{
    cout << max(4,4.2) << endl;;
    cout << max(5,5) << endl;
    int z;
    cin>>z;
}

In the example, you are actually overloading (not specializing) the max<T1,T2> function. Partial specialization syntax should have looked somewhat like below (had it been allowed):

//Partial specialization is not allowed by the spec, though!
template <typename T> 
inline T const& max<T,T> (T const& a, T const& b)
{                  ^^^^^ <--- specializing here
    return 10;
}

[Note: in the case of a function template, only full specialization is allowed by the C++ standard (excluding the compiler extensions).]

Function Templates Partial Specialization in C++, In the example, you are actually overloading (not specializing) the max<T1,T2> function. Partial specialization syntax should have looked somewhat like below  Fall back on class template partial specialization. Even if we can’t do partial specialization on function template, we can do it for class templates. And there is a way to achieve the former by reusing the latter.

Since partial specialization is not allowed -- as other answers pointed --, you could work around it using std::is_same and std::enable_if, as below:

template <typename T, class F>
inline typename std::enable_if<std::is_same<T, int>::value, void>::type
typed_foo(const F& f) {
    std::cout << ">>> messing with ints! " << f << std::endl;
}

template <typename T, class F>
inline typename std::enable_if<std::is_same<T, float>::value, void>::type
typed_foo(const F& f) {
    std::cout << ">>> messing with floats! " << f << std::endl;
}

int main(int argc, char *argv[]) {
    typed_foo<int>("works");
    typed_foo<float>(2);
}

Output:

$ ./a.out 
>>> messing with ints! works
>>> messing with floats! 2

Edit: In case you need to be able to treat all the other cases left, you could add a definition which states that already treated cases should not match -- otherwise you'd fall into ambiguous definitions. The definition could be:

template <typename T, class F>
inline typename std::enable_if<(not std::is_same<T, int>::value)
    and (not std::is_same<T, float>::value), void>::type
typed_foo(const F& f) {
    std::cout << ">>> messing with unknown stuff! " << f << std::endl;
}

int main(int argc, char *argv[]) {
    typed_foo<int>("works");
    typed_foo<float>(2);
    typed_foo<std::string>("either");
}

Which produces:

$ ./a.out 
>>> messing with ints! works
>>> messing with floats! 2
>>> messing with unknown stuff! either

Although this all-cases thing looks a bit boring, since you have to tell the compiler everything you've already done, it's quite doable to treat up to 5 or a few more specializations.

partial template specialization - cppreference.com, In C++, there are class templates and function templates. A partial specialization of (a) for pointer types there's no such thing as a partial specialization Template Specialization In many cases when working with templates, you'll write one generic version for all possible data types and leave it at that--every vector may be implemented in exactly the same way. The idea of template specialization is to override the default template implementation to handle a particular type in a different way.

What is specialization ?

If you really want to understand templates, you should take a look at functional languages. The world of templates in C++ is a purely functional sublanguage of its own.

In functional languages, selections are done using Pattern Matching:

-- An instance of Maybe is either nothing (None) or something (Just a)
-- where a is any type
data Maybe a = None | Just a

-- declare function isJust, which takes a Maybe
-- and checks whether it's None or Just
isJust :: Maybe a -> Bool

-- definition: two cases (_ is a wildcard)
isJust None = False
isJust Just _ = True

As you can see, we overload the definition of isJust.

Well, C++ class templates work exactly the same way. You provide a main declaration, that states the number and nature of the parameters. It can be just a declaration, or also acts as a definition (your choice), and then you can (if you so wish) provide specializations of the pattern and associate to them a different (otherwise it would be silly) version of the class.

For template functions, specialization is somewhat more awkward: it conflicts somewhat with overload resolution. As such, it has been decided that a specialization would relate to a non-specialized version, and specializations would not be considered during overload resolution. Therefore, the algorithm for selecting the right function becomes:

  1. Perform overload resolution, among regular functions and non-specialized templates
  2. If a non-specialized template is selected, check if a specialization exist for it that would be a better match

(for on in-depth treatment, see GotW #49)

As such, template specialization of functions is a second-zone citizen (literally). As far as I am concerned, we would be better off without them: I have yet to encounter a case where a template specialization use could not be solved with overloading instead.

Is this a template specialization ?

No, it is simply an overload, and this is fine. In fact, overloads usually work as we expect them to, while specializations can be surprising (remember the GotW article I linked).

C++ function template partial specialization?, How to use template specialization and partial specialization. (For more on manipulating bits directly, see bitwise operators and bit manipulations in C and C​++.) a function for comparison, you might specialize your template to handle these  the second function template has the same template parameters as the second partial specialization and has just one function parameter whose type is a class template specialization with all the template arguments from the second partial specialization. The function templates are then ranked as if for function template overloading.

Non-class, non-variable partial specialization is not allowed, but as said:

All problems in computer science can be solved by another level of indirection. —— David Wheeler

Adding a class to forward the function call can solve this, here is an example:

template <class Tag, class R, class... Ts>
struct enable_fun_partial_spec;

struct fun_tag {};

template <class R, class... Ts>
constexpr R fun(Ts&&... ts) {
  return enable_fun_partial_spec<fun_tag, R, Ts...>::call(
      std::forward<Ts>(ts)...);
}

template <class R, class... Ts>
struct enable_fun_partial_spec<fun_tag, R, Ts...> {
  constexpr static R call(Ts&&... ts) { return {0}; }
};

template <class R, class T>
struct enable_fun_partial_spec<fun_tag, R, T, T> {
  constexpr static R call(T, T) { return {1}; }
};

template <class R>
struct enable_fun_partial_spec<fun_tag, R, int, int> {
  constexpr static R call(int, int) { return {2}; }
};

template <class R>
struct enable_fun_partial_spec<fun_tag, R, int, char> {
  constexpr static R call(int, char) { return {3}; }
};

template <class R, class T2>
struct enable_fun_partial_spec<fun_tag, R, char, T2> {
  constexpr static R call(char, T2) { return {4}; }
};

static_assert(std::is_same_v<decltype(fun<int>(1, 1)), int>, "");
static_assert(fun<int>(1, 1) == 2, "");

static_assert(std::is_same_v<decltype(fun<char>(1, 1)), char>, "");
static_assert(fun<char>(1, 1) == 2, "");

static_assert(std::is_same_v<decltype(fun<long>(1L, 1L)), long>, "");
static_assert(fun<long>(1L, 1L) == 1, "");

static_assert(std::is_same_v<decltype(fun<double>(1L, 1L)), double>, "");
static_assert(fun<double>(1L, 1L) == 1, "");

static_assert(std::is_same_v<decltype(fun<int>(1u, 1)), int>, "");
static_assert(fun<int>(1u, 1) == 0, "");

static_assert(std::is_same_v<decltype(fun<char>(1, 'c')), char>, "");
static_assert(fun<char>(1, 'c') == 3, "");

static_assert(std::is_same_v<decltype(fun<unsigned>('c', 1)), unsigned>, "");
static_assert(fun<unsigned>('c', 1) == 4, "");

static_assert(std::is_same_v<decltype(fun<unsigned>(10.0, 1)), unsigned>, "");
static_assert(fun<unsigned>(10.0, 1) == 0, "");

static_assert(
    std::is_same_v<decltype(fun<double>(1, 2, 3, 'a', "bbb")), double>, "");
static_assert(fun<double>(1, 2, 3, 'a', "bbb") == 0, "");

static_assert(std::is_same_v<decltype(fun<unsigned>()), unsigned>, "");
static_assert(fun<unsigned>() == 0, "");

Why Not Specialize Function Templates?, This class takes two template parameters, a type parameter, and an expression parameter. Now, let's say we wanted to write a function to print out  Partial specialization allows template code to be partially customized for specific types in situations, such as: A template has multiple types and only some of them need to be specialized. The result is a template parameterized on the remaining types. A template has only one type, but a specialization is needed

No. For example, you can legally specialize std::swap, but you cannot legally define your own overload. That means that you cannot make std::swap work for your own custom class template.

Overloading and partial specialization can have the same effect in some cases, but far from all.

Template Specialization and Partial Specialization in C++ , template <class T, T t> struct C {}; // primary template template <class T> struct C<​T, 1>; Partial template specializations are not found by name lookup. s = 1; }; // partial specialization #1 // fictitious function template for #1 is // template<int I,  So the reason cannot be that function templates can only be fully specialized, because the third example is not a full specialization (the template parameter U is still there), and yet it works. c++ templates template-specialization partial-specialization

13.7, The compiler uses the partial specialization if its template argument list matches a subset of You cannot partially specialize function templates. int main() { X<​int, int, 10> a; X<int, int*, 5> b; X<int*, float, 10> c; X<int, char*, 10> d; X<float, int*,​  Well, you really can't do partial function/method specialization however you can do overloading. template <typename T, typename U> T fun(U pObj){} // acts like partial specialization <T, int> AFAIK // (based on Modern C++ Design by Alexandrescu) template <typename T> T fun(int pObj){} It is the way but I do not know if it satisfy you.

partial template specialization, 13.7.5 Class template partial specializations [temp.class.spec]. 1. # template A and the function template D is more specialized than the function template C. A function with the same name and the same argument list as a specialization is not a specialization (see template overloading in function template) . An explicit specialization of a function template is inline only if it is declared with the inline specifier (or defined as deleted), it doesn't matter if the primary template is inline.

Partial specialization, Template Specialization in C++ 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.

Comments
  • Look for that analogy of class specialization. If it is called class specialization, then why I should consider the same thing for function as overloading??
  • No, specialization syntax is different. Look at the (supposed) function specialization syntax in my answer below.
  • Why doesn't this throw a "Call to max is ambigious" error? How does max(5,5) resolve to max(T const&, T const&) [with T=int] and not max(T1 const&, T2 const&) [with T1=int and T2=int]?
  • @Narek, Partial function specialization is not part of standard (for whatsoever reasons). I think MSVC supports it as an extension. May be after sometime, it would be allowed by other compilers also.
  • @iammilind: No problem. He already seems to know that. That is why he is trying that for function template as well. So I edited it again, making it clear now.
  • Anyone who can explain why partial specialization isn't allowed?
  • @NHDaly, It doesn't give ambiguity error because 1 function is better match than the other. Why it selects (T, T) over (T1, T2) for (int, int), is because the former guarantees that there are 2 parameters and both types are same; the latter only guarantees that there are 2 parameters. Compiler chooses always an accurate description. e.g. If you have to make a choice between 2 descriptions of a "River" which one would you choose? "collection of water" vs "collection of Water flowing".
  • @kfsone, I think this feature is under review, hence open for interpretation. You may refer this open-std section, which I saw in Why does the C++ standard not allow function template partial specialization?
  • There really isn't any need to do this as this can be handled by function overloading in a much simpler and clearer fashion.
  • @Adrian I really can't think of any other function overloading approach to solve this. You noticed partial overloading is not allowed, right? Share with us your solution, if you think it is clearer.
  • is there any other way to do easily catch all templated function?
  • "As such, template specialization of functions is a second-zone citizen (literally). As far as I am concerned, we would be better off without them: I have yet to encounter a case where a template specialization use could not be solved with overloading instead." How about with non type template parameters?
  • @Julius: you can still use overloading, albeit by introducing a dummy parameter such as boost::mpl::integral_c<unsigned, 3u>. Another solution could also be to use enable_if/disable_if, though it's a different story.
  • That's why you put your swap overload in your namespace.