When I first learned how to check a specific signature in a class, I was taught to use std::void_t
and write some code like this:
template<typename T, typename =void>
class HAS:public false_type{};
template<typename T>
class HAS<T,void_t<decltype(declval<T>().print())>>:public true_type{};
And this snippet of code will check if a class has the method named "print()
". It works well.
But when I tried to remove the std::void_t
, it still worked.
The code looks like this:
template<typename T, typename = void>
class HAS:public false_type{};
template<typename T>
class HAS<T,decltype(declval<T>().print())>:public true_type{};
So I am confused if "std::void_t
" is necessary to check if a class has a method with a specific signature? Or that's only a coincidence?
This question explains in detail how void_t
(otherwise known as the detection idiom) works. The key point is that the specialisation will only be considered if the type of the second template parameter evaluates to void
.
In this case, it just so happens that your print()
method returns void
, so decltype(declval<T>().print())
is also void. But if your print()
returned something else, say bool
, then the specialisation would not match and would not be used.
"void_t" is necessary to check if a class has a method with a specific signature?
+1 for the Tristan Brinde answer; but my answer is: std::void_t
helps but (in your case) isn't necessary.
You can use the comma trick
decltype(std::declval<T>().print(), void())
The following is a compiling (in C++11 too; std::void_t
is available only from C++17) full example
struct foo
{ };
struct bar
{ int print () const { return 0; } };
template <typename T, typename = void>
class HAS
: public std::false_type
{ };
template <typename T>
class HAS<T, decltype(std::declval<T>().print(), void())>
: public std::true_type
{ };
int main ()
{
static_assert( HAS<foo>::value == false, "!" );
static_assert( HAS<bar>::value == true, "!!" );
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With