Mr.C64 - 6 months ago 51

C++ Question

I have a function template and I'd like to restrict the set of types for which it can be instantiated.

I wrote something like this:

`template <typename T>`

void DoSomething( /* ... Some parameters involving T ... */)

{

// Check at compile-time that T is allowed

static_assert(

std::is_same<T, int>::value

|| std::is_same<T, float>::value

|| std::is_same<T, double>::value

...

|| std::is_same<T, /* other type */>::value,

"Type not allowed");

}

I have to repeat the same check for other function templates.

An obvious solution would be copy-and-paste'ing the above

`static_assert`

A better solution might be to wrap the

`static_assert`

But what I think would be more elegant is defining a

`std::is_same`

`static_assert(IsTypeAllowed<T>::value, "Type not allowed");`

How can I define my custom

`IsTypeAllowed<T>`

`std::is_same`

`||`

Answer

In C++1z you can roll your own trait with `std::disjunction`

:

```
template<typename T, typename... Others>
struct is_any : std::disjunction<std::is_same<T, Others>...>
{
};
```

Then it's as simple as

```
static_assert(!is_any<int,char,bool>::value);
//static_assert(!is_any<int,char,bool,int>::value); //error
```

You can map it further to get the exact interface you asked for:

```
template<typename T>
using IsTypeAllowed = std::bool_constant<!is_any<T, char, bool, int>>;
```

If you need this in C++14, you needn't look father than the possible implementation provided by cppreference:

```
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<B1::value != false, B1, disjunction<Bn...>> { };
```