3

1) I have two classes class A and class B which both have a method called foo but with different argument lists.

class A {
public:
  void foo(int a);
};

class B {
public:
  void foo(int a, int b);
};

2) Further, I have a class C with template argument T that also has a foo method as following

template <typename T>
class C {
public:
  void foo();
private:
  T t_;
  int a_;
  int b_;
};

3) I would like use both class A and class B as template argument for class C. Saying that I would like to have a method C::foo to be implemented like following:

template <typename T>
void C<T>::foo()
{
  if (compile time check: T has foo(int a, int b))
   t_.foo(a_, b_);
  else
   t_.foo(a_);
}

How can I express the if statement above in C++11?

TruLa
  • 1,031
  • 11
  • 21

2 Answers2

6

Use SFINAE (with function template overloading).

template <typename T>
class C {
private:
    T t_;
    int a_;
    int b_;
public:
    template <typename X = T>
    auto foo() -> decltype (std::declval<X>().foo(a_)) {
        t_.foo(a_);
    }
    template <typename X = T>
    auto foo() -> decltype (std::declval<X>().foo(a_, b_)) {
        t_.foo(a_, b_);
    }
};

LIVE

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
4

If you know which type contains void foo(int a, int b); which in this case you do, you can use template specialization, something like

template <typename T>
class C
{
private:
  T t_;
  int a_;
  int b_;
public:
    // called for general use
    void foo()
    {
        t_.foo(a_);
    }
};

// specialized version for T = B
template<> 
void C<B>::foo()
{
    t_.foo(a_, b_);
}
George
  • 2,101
  • 1
  • 13
  • 27