4

I have a class like this:

template <unsigned int A, unsigned int B>
class Foo { ... };

Foo needs a method called bar(), but I need to specialise this. For a case, when A == B, I want it to do a thing, and something else otherwise. Can I do this without writing an if statement into the function? Like:

Foo<A, A>::bar() { ... } and Foo<A, B>::bar() { ... }
Peter Lenkefi
  • 1,306
  • 11
  • 29

2 Answers2

5

You can partially specialize your class:

#include<cassert>

template<typename A, typename B>
struct S {
    void f(int i) { assert(i == 42); }
};

template<typename A>
struct S<A, A> {
    void f(int i) { assert(i == 0); }
};

int main() {
    S<int, double> s1;
    S<int, int> s2;
    s1.f(42);
    s2.f(0);
}
skypjack
  • 49,335
  • 19
  • 95
  • 187
3

Another solution to partial specialization is enable_if. I have assumed you have integer template parameters, but if you have types you can use std::is_same<TA,TB>.

This answer is based on solutions from here: std::enable_if to conditionally compile a member function

http://coliru.stacked-crooked.com/a/692fbfff1b9d84e8

#include <iostream>
#include <string>

template <unsigned int A, unsigned int B>
class Foo { 
    public:

        template<unsigned int TA=A, unsigned int TB=B>
        typename std::enable_if< TA == TB >::type
        bar() {
         std::cout << "equal version = " << A << "  " << B << "\n";
        }

        template<unsigned int TA=A, unsigned int TB=B>
        typename std::enable_if< TA != TB >::type
        bar() {
         std::cout << "NON equal version = " << A << "  " << B << "\n";
        }
};

int main()
{
    Foo<1, 1> f1;
    f1.bar();

    Foo<1, 2> f2;
    f2.bar();    
    return 0;
}

outputs:

equal version = 1  1
NON equal version = 1  2

Example for typed template parameters:

http://coliru.stacked-crooked.com/a/05d6a93480e870aa

#include <iostream>
#include <string>

template <typename A, typename B>
class Foo { 
    public:

        template<typename TA=A, typename TB=B>
        typename std::enable_if<std::is_same<TA, TB>::value>::type
        bar() {
         std::cout << "equal version" << "\n";
        }

        template<typename TA=A, typename TB=B>
        typename std::enable_if<!std::is_same<TA, TB>::value>::type
        bar() {

         // This will cause compilation error if this bar() overload is to be instantiated
         // but since it is not there is no compilation error
         typename TA::non_exists ii = 0;
         std::cout << "NON equal version" << "\n";
        }
};
int main()
{
    Foo<int, int> f1;
    f1.bar();

    //Foo<int, float> f2;
    //f2.bar();    
    return 0;
}
Community
  • 1
  • 1
marcinj
  • 48,511
  • 9
  • 79
  • 100