Ссылка на значение r c ++ применяется к указателю на функцию - PullRequest
1 голос
/ 23 февраля 2020
#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;
}

Согласно f1 печать не является функцией.

Согласно f2 печать является функцией.

Понимание того, почему это так, поможет понять оператор &&

1 Ответ

1 голос
/ 23 февраля 2020

В обоих случаях функция передается по ссылке. И обе функции имеют отношение к lvalue-ссылке на функцию print.

Используйте

std::is_function_v<std::remove_reference_t<T>>

вместо

std::is_function_v<typename std::remove_pointer_t<T>>

Вы также можете вставить такое утверждение в Обе функции

std::cout << std::is_lvalue_reference_v<decltype( t )> << '\n';

, чтобы убедиться, что функции работают с lvalue-ссылкой на rpint.

Учтите, что вам нужно включить заголовок <type_traits>.

Если вы хотите, чтобы функции имели дело с указателями на функции, вам нужно использовать такой вызов

f1(&print);

В этом случае вторая функция должна быть объявлена ​​как

template<typename T>
void f2( const T& t);

В противном случае Вы не можете привязывать непостоянную ссылку к rvalue.

Или вызывать функцию f2, как если вы не хотите использовать квалификатор const.

auto p = print;

f2(p);
...