Reputation: 921
As far my understanding goes I want to restrict only 2 types int and string for the following class, just like in java template definition with extends.
template<typename T>
typename std::enable_if<std::is_same<T,int>::value || std::is_same<T,string>::value>::type
class ExchangeSort
{
public:
void bubbleSort(T buffer[], int s);
void print(T buffer[], int s);
void bubbleSort(const vector<T>& vec);
};
But if I'm instantiating like below
ExchangeSort<int>* sortArray = new ExchangeSort<int>;
I'm getting errors for the above line ExchangeSort is undefined. What is the problem ?
Upvotes: 1
Views: 34
Reputation: 69864
Here's another way which allows the possibility of adding further specialisations down the line:
#include <type_traits>
#include <vector>
#include <string>
//
// Step 1 : polyfill missing c++17 concepts
//
namespace notstd {
template<class...> struct disjunction : std::false_type { };
template<class B1> struct disjunction<B1> : B1 { };
template<class B1, class... Bn>
struct disjunction<B1, Bn...>
: std::conditional_t<bool(B1::value), B1, disjunction<Bn...>> { };
}
//
// Step 2 : create a test to see if a type is in a list
//
namespace detail {
template<class T, class...Us>
struct is_one_of : notstd::disjunction< std::is_same<T, Us>... > {};
}
template<class T, class...Us>
static constexpr auto IsOneOf = detail::is_one_of<T, Us...>::value;
//
// Step 3 : declare the default specialisation, but don't define it
//
template<class T, typename Enable = void>
struct ExchangeSort;
//
// Step 4 : define the specialisations we want
//
template<typename T>
class ExchangeSort<T, std::enable_if_t<IsOneOf<T, int, std::string>>>
{
public:
void bubbleSort(T buffer[], int s);
void print(T buffer[], int s);
void bubbleSort(const std::vector<T>& vec);
};
//
// Test
//
int main()
{
auto esi = ExchangeSort<int>();
auto ess = ExchangeSort<std::string>();
// won't compile
// auto esd = ExchangeSort<double>();
}
Upvotes: 0
Reputation: 171117
SFINAE can be used to conditionally disable function overloads or template specialisations. It makes no sense to try to use it to disable a class template, since class templates cannot be overloaded. You'll be better off using a static assertion:
template<typename T>
class ExchangeSort
{
static_assert(std::is_same<T,int>::value || std::is_same<T,string>::value, "ExchangeSort requires int or string");
public:
// The rest as before
As to the errors you were getting, the code didn't make syntactic sense. enable_if
can only appear where a type is expected. With functions, it's often used to wrap the return type, in which case it's syntactically similar to what you wrote. But with classes, there's no type between template
and the class definition.
Upvotes: 1