3

I am using C++ and templates - but I need to allow using a member function for a specific type and prevent other types from using this function.

For example: I want this class to have print() for all types but have foo() for just type int. How can I do that ?

#include<iostream>

template <class type>
class example
{
private:
    type data;

public:
    void print(); // for all types

    void foo();   // only for 'type' == int?
};
Barry
  • 286,269
  • 29
  • 621
  • 977
Youssef Emad
  • 319
  • 2
  • 13

3 Answers3

4

Factor the common, generic functionality into a base class. Specializations can inherit that.

namespace detail {

template <class type>
class example_base
{
private:
type data ;

public:
void print();
};

} // end namespace detail

template <class type>
struct example
    : detail::example_base<type> {
    using detail::example_base<type>::example_base; // inherit any constructors
};

template <> // specialize the class
struct example< int >
    : detail::example_base<int> {
    using detail::example_base<int>::example_base; // inherit any constructors

    void other_function(); // extend the basic functionality
};
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
3

You could use std::enable_if and do something like this to obtain exactly what you want:

#include <iostream>
#include <type_traits>

template<class T>
class example
{
   private:
      T data;
   public:
      void print() 
      { 
         std::cout << " hello " << std::endl;
      }

      template<class U = T // make the function templated on U, but with default type T
             , typename std::enable_if<std::is_integral<U>::value>::type* = nullptr // enable only for when U (T) is an integral type
             >
      void foo()
      {
         std::cout << " I will only compile when T is an integral type " << std::endl;
      }
};


int main()
{
   example<int> integer_example;
   integer_example.print();
   integer_example.foo(); // <--- compiles fine as int is integral

   example<double> double_example;
   double_example.print();
   //double_example.foo(); // <--- will not compile

   return 0;
}

In the std::enable_if you can also put std::is_same<U,int>::value instead of std::is_integral<U>::value to only allow the function only to be used for int and not other integral types.

Banan
  • 434
  • 6
  • 12
2

You can specify the template for some types. See this example :

template <typename T>
class MyClass
{
  private:
    double my_function() { return 1.0; }
};

template <>
class MyClass<double>
{
  public:
    double my_function() { return 2.0; }
};

int main()
{
  MyClass<double> a;
  MyClass<int> b;
  double x = a.my_function();  // this works
  // double y = b.my_function(); // not allowed
  return 0;
}

Tested with GCC 4.7.2.

Caduchon
  • 4,574
  • 4
  • 26
  • 67