Search code examples
c++language-designtemplate-specializationpartial-specializationfunction-templates

Why can function templates not be partially specialized?


I know the language specification forbids partial specialization of function template.

I would like to know the rationale why it forbids it? Are they not useful?

template<typename T, typename U> void f() {}   //allowed!
template<> void f<int, char>()            {}   //allowed!
template<typename T> void f<char, T>()    {}   //not allowed!
template<typename T> void f<T, int>()     {}   //not allowed!

Solution

  • AFAIK that's changed in C++0x.

    I guess it was just an oversight (considering that you can always get the partial specialization effect with more verbose code, by placing the function as a static member of a class).

    You might look up the relevant DR (Defect Report), if there is one.

    EDIT: checking this, I find that others have also believed that, but no-one is able to find any such support in the draft standard. This SO thread seems to indicate that partial specialization of function templates is not supported in C++0x.

    EDIT 2: just an example of what I meant by "placing the function as a static member of a class":

    #include <iostream>
    using namespace std;
    
    // template<typename T, typename U> void f() {}   //allowed!
    // template<> void f<int, char>()            {}   //allowed!
    // template<typename T> void f<char, T>()    {}   //not allowed!
    // template<typename T> void f<T, int>()     {}   //not allowed!
    
    void say( char const s[] ) { std::cout << s << std::endl; }
    
    namespace detail {
        template< class T, class U >
        struct F {
            static void impl() { say( "1. primary template" ); }
        };
    
        template<>
        struct F<int, char> {
            static void impl() { say( "2. <int, char> explicit specialization" ); }
        };
    
        template< class T >
        struct F< char, T > {
            static void impl() { say( "3. <char, T> partial specialization" ); }
        };
    
        template< class T >
        struct F< T, int > {
            static void impl() { say( "4. <T, int> partial specialization" ); }
        };
    }  // namespace detail
    
    template< class T, class U >
    void f() { detail::F<T, U>::impl(); }    
    
    int main() {
        f<char const*, double>();       // 1
        f<int, char>();                 // 2
        f<char, double>();              // 3
        f<double, int>();               // 4
    }