C++ single template specialisation with multiple template parameters

20,948

Solution 1

You have to provide a partial specialization of the class template B:

template <typename I>
class B<float, I>
{
public:
    void someFunc();
};

template <typename I>
void B<float, I>::someFunc()
{
    ...
}

You can also just define someFunc inside the specialization.

However, if you only want to specialize a function, and not a class do e. g.

template <typename F, typename I>
void someFunc(F f, I i) { someFuncImpl::act(f, i); }

template <typename F, typename I>
struct someFuncImpl { static void act(F f, I i) { ... } };

// Partial specialization
template <typename I>
struct someFuncImpl<float, I> { static void act(float f, I i) { ... } };

But you can't specialize a function template without this trick.

Solution 2

Although you can totally specialize member functions of a class template, you cannot _partially specialize member functions. - Andrei Alexandrescu

Partial Class specialization is explained by the other posters.

You can, however, use overloading:

template <class T, class U> T fun(U obj); // primary template
template <class U> void Fun<void, U>(U obj); // illegal pertial
// specialization
template <class T> T fun (Window obj); // legal (overloading)

If you want to go deep into this, you can read about this issue in depth in "Modern C++ Design" by A. Alexandrescu.

Share:
20,948
tauran
Author by

tauran

Updated on July 26, 2021

Comments

  • tauran
    tauran almost 3 years

    Hallo!

    I would like to specialise only one of two template types. E.g. template <typename A, typename B> class X should have a special implementation for a single function X<float, sometype>::someFunc().

    Sample code:

    main.h:

    #include <iostream>
    
    template <typename F, typename I>
    class B
    {
    public:
        void someFunc()
        {
            std::cout << "normal" << std::endl;
        };
    
        void someFuncNotSpecial()
        {
            std::cout << "normal" << std::endl;
        };
    };
    
    template <typename I>
    void B<float, I>::someFunc();
    

    main.cpp:

    #include <iostream>
    #include "main.h"
    
    using namespace std;
    
    template <typename I>
    void B<float, I>::someFunc()
    {
        cout << "special" << endl;
    }
    
    int main(int argc, char *argv[])
    {
        B<int, int> b1;
        b1.someFunc();
        b1.someFuncNotSpecial();
    
        B<float, int> b2;
        b2.someFunc();
        b2.someFuncNotSpecial();
    }
    

    Compilation fails for class B. Is it true, that this is not possible in C++ in this way? What would be the best workaround?

    [edit]

    template <float, typename I> void B<float, I>::someFunc(); leads to main.h:26: error: ‘float’ is not a valid type for a template constant parameter

    template <typename I> void B<float, I>::someFunc(); leads to main.h:27: error: invalid use of incomplete type ‘class B’

    And I'm using gcc.

    [edit]

    I don't want to specialise the whole class, as there are other functions that don't have a specialisation.