Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a standard generalization of void_t for other types?

Tags:

c++

c++17

sfinae

In C++17, we have std::void_t, which makes SFINAE look a lot nicer:

template <typename T>
std::void_t<decltype(T::prop)> foo() { /* stuff */ }

The template function will exist only if T::prop exists.

If T::prop exists, the template function foo() would be equivalent to this:

template <typename T>
void foo() { /* stuff */ }

Otherwise, the code is equivalent to not declaring foo() at all.

Is there any generalization of std::void_t for other types in the standard library, such as the following:

template<typename T, typename...>
using generic_t = T;

so that the code below would be valid?

template <typename T>
std::generic_t<int, decltype(T::prop)> foo() { /* stuff */ }

which would be equivalent to

template <typename T>
int foo() { /* stuff */ }

if T::prop exists?

like image 949
Bernard Avatar asked Jun 23 '17 07:06

Bernard


People also ask

What is void_T in C++?

void_t is a meta-function that maps any (number of) types to type void. The primary purpose of void_t is to facilitate writing of type traits. std::void_t will be part of C++17, but until then, it is extremely straightforward to implement: template <class...> using void_t = void;

What is the primary application of void_T?

The primary application of void_t is writing type traits that check validity of a statement. For example, let's check if a type has a member function foo () that takes no arguments: How does this work?

What is generalization in Java?

Converting a subclass type into a superclass type is called ‘ Generalization ‘ because we are making the subclass to become more general and its scope is widening. This is also called widening or up casting. Widening is safe because the classes will become more general.

Why cast operator is not used in generalization in Java?

Thus Java compiler will not ask for cast operator in generalization. So, in widening or Generalization, we can access all the superclass methods, but not the subclass methods. Converting a super class type into a sub class type is called ‘ Specialization ‘.


2 Answers

Why do you need such a generalization? void_t is a little special in that it helps you easily write type traits, because you can have a primary with some type defaulted to void and a specialization which uses void_t. For instance:

template <class T, class = void>
struct has_prop : std::false_type { };

template <class T>
struct has_prop<T, std::void_t<decltype(T::prop)>> : std::true_type { };

It's not that there's anything special about void, you just need some agreed upon type between the primary and the specialization.

void_t doesn't make much sense if you're just using it directly in SFINAE though. You could just stick the expression somewhere else:

template <typename T, class = decltype(T::prop)>
void foo() { /* stuff */ }

at which point the return type is totally separate from the condition you're checking anyway, so if you want int:

template <typename T, class = decltype(T::prop)>
int foo() { /* stuff */ }
like image 51
Barry Avatar answered Sep 20 '22 05:09

Barry


It probably does not exist. It is not linked in the documentation and therefore I doubt its existence. But you can build such type on your own:

template <class type, class... sfinae_expressions>
using generic_t = type;
like image 21
OutOfBound Avatar answered Sep 22 '22 05:09

OutOfBound