Reputation: 4401
#include <iostream>
#include <utility>
template<typename T>
void f1(T&& t) // &&
{
if constexpr (std::is_function_v<typename std::remove_pointer_t<T>>)
std::cout << "function" << std::endl;
else
std::cout << "not a function" << std::endl;
}
template<typename T>
void f2(T& t) // &
{
if constexpr (std::is_function_v<typename std::remove_pointer_t<T>>)
std::cout << "function" << std::endl;
else
std::cout << "not a function" << std::endl;
}
void print(){}
int main()
{
f1(print);
f2(print);
return 0;
}
According to f1, print is not a function.
According to f2, print is a function.
Understanding why this is so would help understanding the && operator
Upvotes: 1
Views: 1078
Reputation: 310960
In the both cases a function is passed by reference. And the both functions deals with lvalue reference to the function print.
Use
std::is_function_v<std::remove_reference_t<T>>
instead of
std::is_function_v<typename std::remove_pointer_t<T>>
You can also insert a statement like this in the both functions
std::cout << std::is_lvalue_reference_v<decltype( t )> << '\n';
to be sure that the functions deal with the lvalue reference to rpint.
Take into account that you need to include the header <type_traits>
.
If you want that the functions would deal with function pointers then you need to use a call like this
f1(&print);
In this case the second function should be declared like
template<typename T>
void f2( const T& t);
Otherwise you may not bind a non-constant reference to rvalue.
Or call the function f2 like if you do not want to use the qualifier const.
auto p = print;
f2(p);
Upvotes: 1