I was looking into decltype
and std::is_same_v
and tried them on functions.
template<typename T>
void func(T t){}
template<typename T>
using f = decltype(func<T>);
template<typename T>
using ff = decltype((func<T>));
template<typename T>
using fff = void(*)(T);
template<typename T, typename U, typename Z>
void test(T t, U u, Z z){
std::cout << __PRETTY_FUNCTION__ << std::endl;
std::cout << std::boolalpha
<< std::is_same_v<T, U> << " "
<< std::is_same_v<U, Z> << " "
<< std::is_same_v<Z, T>;
}
int main()
{
f<int> f1; // 1
ff<int> ff1 = func<int>; // 2
fff<int> fff1 = func<int>;
test(f1, ff1, fff1);
return 0;
}
Output:
void test(T, U, Z) [with T = void (*)(int); U = void (*)(int); Z = void (*)(int)]
true true true
While editing I removed parameter by mistake and ran the code. link to the demo
template<typename T, typename U, typename Z>
void test(T t, U u) // Z z is missing
{ // nothing changed in the body }
no matching function for call to 'test(void (&)(int), void (&)(int), void (*&)(int))'
36 | test(f1, ff1, fff1);
| ^
It looks like Z
is different type but std::is_same_v<U, Z>
gives true
. And I thought ff
and f
would be different types as per decltype
in cpprefernce
Note that if the name of an object is parenthesized, it is treated as an ordinary lvalue expression, thus decltype(x) and decltype((x)) are often different types.
f f1 = func<int>;
I get a warning and an error. warning: declaration of 'void f1(int)' has 'extern' and is initialized
32 | f<int> f1 =func<int>;
| ^~
<source>:32:16: error: function 'void f1(int)' is initialized like a variable
32 | f<int> f1 =func<int>;
| ^~~~~~~~~
ff ff1;
I get an error sayingerror: 'ff1' declared as reference but not initialized
33 | ff<int> ff1 ;
| ^~~
As far as I know, I got reference type due to decltype((func<T>))
but std::is_same_v
gave true
in test
.
Apparenlty, std::is_same_v
tells all three are same yet they are different. I'm a beginner in c++ and I'm not able to comprehend what's going.
Your code is similar to:
f<int> f1; // `void f1(int);`, function declaration
ff<int> ff1 = func<int>; // `void (&ff1)(int) = func<int>;`, reference to function
fff<int> fff1 = func<int>; // `void (*fff1)(int) = &func<int>;` pointer to function,
// decay of `func<int>` to pointer
As C-array, you cannot pass function by value; they decay to pointer.
so
test(f1, ff1, fff1); // test(&f1, &ff1, fff1);
and inside test, all parameter have void (*)(int)
type.