-2

Following Template class type-specific functions, how can I customize my template code to not compile for certain types? If the question is not clear, take a look at this example.

///** template class ***/
template<typename T>
class testClass{
testClass();
T parameter;
}
template<typename T>
void testClass<T>::print(){cout<<parameter.value<<endl;}

The above class is supposed to work for the following types:

 //** types file **/
    class paramtype1{
    int value;
    }
    class paramtype2{
    int value;
    }
    class paramtype3{
    }

As you see, paramtype3 doesn't have value, so I get a compile error saying that value is not defined. I know that if I want to specialize a template class function for a certain type (s), I need to do:

template<>
void testClass<paramtype1>::print(){cout<<parameter.value<<endl;}

But, is there any way to do the other way around, only excluding some certain types?

max66
  • 65,235
  • 10
  • 71
  • 111
JNo
  • 89
  • 12
  • You should edit your question to include what types *specifically* you want to include/exclude, **and why**. If you want to enable a specialization only if a type has a particular member, you'd use different techniques. – Sneftel Jul 25 '19 at 12:11
  • Also, you got a compiler error when you tried to use the template with `paramtype3`... doesn't that mean it *already* didn't compile for that type? – Sneftel Jul 25 '19 at 12:13

2 Answers2

3

If you want enable/disable the full class/struct, you can use SFINAE and partial specialization.

The following is a C++17 example

template <typename T, typename = void>
struct testClass;

template <typename T>
struct testClass<T, std::void_t<decltype(T::value)>>
 {
   testClass()
    { };

   T parameter;

   void print()
    { std::cout << parameter.value << std::endl; }
 };

If you only want enable/disable the print() function, you have to templatize it; by example

template <typename U = T>
std::void_t<decltype(U::value)> print()
 { std::cout << parameter.value << std::endl; }

or also

template <typename U = T>
std::void_t<decltype(U::value), std::enable_if_t<std::is_same_v<U, T>>> 
    print()
 { std::cout << parameter.value << std::endl; }

if you want to be sure that nobody can "hijack" the method explicating the template type calling

testClass<paramtype3>{}.print<paramtype1>():
max66
  • 65,235
  • 10
  • 71
  • 111
2

What I would personally do to exclude permissions to use certain types is:

template <class T, class... Ts>
struct is_any : std::disjunction<std::is_same<T, Ts>...> {};

// https://stackoverflow.com/questions/17032310/how-to-make-a-variadic-is-same

template <typename T>
void do_something() {
    static_assert(!is_any<T, int, bool>::value, "do_something<T> cannot be used with T as int or bool");
    // code here
}

Allows you to add a custom assertion message aswel, making it easy to realise what's wrong.

JohnkaS
  • 622
  • 8
  • 18