I met a decltype() with two parameters as return value type of template function:
template<class C, class F>
auto test(C c, F f) -> decltype((void)(c.*f)(), void()) { }
Does someone knows what is the second parameter, void()?
Thank you very much.
In the expression (void)(c.*f)(), void():
(void)(c.*f)() serves to check that f is a member function in c that can be called with no arguments; it doesn't matter what the member-function return type is anyway, but it's nominally cast to void
if the above is valid, the comma operator discards it and considers the second part, such that the overall effect is per decltype(void()), which yields a void type
Praetorian comments below that the trailing , void() is redundant, as the leading part is cast to void (the C-style cast (void)) anyway... I suspect the , void() is intended as documentation, highlighting the enable_if-like conditional selection of a return type, it's a style choice whether to shorten that further to decltype((c.*f)(), void()).
This can be used for SFINAE, though enable_if is more self-documenting. Consider this code, and the comments in main() (CT stands for Compile Time):
#include <iostream>
template<class C, class F>
auto test(C c, F f) -> decltype((void)(c.*f)(), void())
{ std::cout << "member function\n"; }
template<class C>
void test(C c, int)
{ std::cout << "int\n"; }
struct X {
int f() { return 42; }
double g(int) { return 3.14; }
};
int main()
{
X x;
test(x, &X::f); // ok - outputs "member function\n"
// test(x, &X::g); // CT error - g needs an argument
test(x, 99); // ok - outputs "int\n"
}
Output:
member function
int
You can see and run the code here.
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