Search code examples
c++pass-by-referencefunction-pointersrvalue

c++ r-value reference applied to function pointer


#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


Solution

  • 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);