1

I am interested in defining a custom method for a generic class for only a particular data type. I am not sure whats a good way to implement it. I won't be able to access class variables if I place it outside the class so I think i can never get it to work that way. If i place it inside the class, its meant to work for any type T and not just the particular type. I have been able to get my code to work the latter way by just defining a generic version of it and sending only that type as input which i m interested in but is there a neater way to accomplish this?

Below is some code to make it clear

#include<iostream>
#include<string>
using namespace std;

template<typename  T>
class abc
{
public:
    void myvoid();
};

template<typename string>
void abc<string>::myvoid()
{
    cout<<"This portion should execute only if an instance of class is called with a    string parameter" ;
}

int main()
{
abc<int> int1;
abc<string> string1;
string1.myvoid(); //should work good
int1.myvoid(); //shouldnt execute myvoid
}  
Akash Rupela
  • 159
  • 10

2 Answers2

4

You can use static_assert to prevent compilation if the method in question is used with the wrong type:

#include <type_traits> // for std::is_same

template <typename T>
struct Foo
{
  void foo() const {}
  void bar() const
  {
    static_assert(std::is_same<T, int>::value, "T is not int");
  }
};

int main()
{
  Foo<double> fd;
  fd.foo();       // OK
  //fd.bar();     // ERROR: bar() only works with Foo<int>
  Foo<int> fi;
  fi.foo();       // OK
  fi.bar();       // OK
}

Alternatively, you can use SFINAE to control the types for which the method in question exists.

template <typename T>
class Foo
{
 public:
  void foo() const {}

  template<typename T2 = T,
           typename = typename std::enable_if<std::is_same<T, int>::value>::type>
  void bar() {}
};

See this related question.

Community
  • 1
  • 1
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • I think Akash meant that this method should not work for any T, but only for one special case of T while all other methods should work for all types. – Coert Metz Aug 17 '13 at 14:04
  • @CoertMetz probably, but probably not. The question can be interpreted in many ways. – juanchopanza Aug 17 '13 at 14:05
  • Apparently, the question wassnt clear. I did not know how to put it up. My method is supposed to work only for a special case of T while all other methods work for all types as Coert pointed out . – Akash Rupela Aug 17 '13 at 14:07
  • @AkashRupela what should the method do for all other types? Should it not exist, or raise a compilation error if used? – juanchopanza Aug 17 '13 at 14:10
  • @juanchopanza, Either would do great. – Akash Rupela Aug 17 '13 at 14:11
  • @AkashRupela OK, I added an example where compilation fails if you attempt to use the method with the wrong `T`. – juanchopanza Aug 17 '13 at 14:17
  • @CoertMetz It turns out you were right. I completely changed the answer now. – juanchopanza Aug 17 '13 at 14:26
  • @juanchopanza , Thankyou, this seems to be exactly what i want. But there seems some problem with the "is_same" part. Error: is_same is not a member of std? I m presuming it has to do with my version of c++ – Akash Rupela Aug 17 '13 at 14:27
  • @AkashRupela Did you `#include `? – Casey Aug 17 '13 at 14:28
  • @Casey, I just now enabled the c+11 compiler and now it works. The code compiles with an error now everytime I have used a bad type in the program. I put is_same in a conditional statement and can now manipulate it anyway. Thanks a lot guys :) – Akash Rupela Aug 17 '13 at 14:41
  • I think the SFINAE approach (shown in the link) is better, having no function with assert (although static_assert) in the first place. –  Aug 17 '13 at 14:59
1

This will give a linker error if you try to call bar() on a non-specialized type. This works on gcc 4.8 (see: http://ideone.com/KbwToR)

#include <iostream>
using namespace std;

struct Foo
{
   template <class T>
   void bar(T);
};

template<>
void Foo::bar<int>(int i)
{
   cout << i << '\n';
}

int main()
{
   Foo f;

   f.bar(1);
   f.bar("Fail!");

   return 0;
}
Chad
  • 18,706
  • 4
  • 46
  • 63