Как использовать переадресацию для приведения rvalue к lvalue? - PullRequest
0 голосов
/ 13 мая 2019

Я пытаюсь использовать перегруженную функцию, чтобы скрыть передачу ссылки int на функцию утилиты, когда мне нет дела до возвращаемых данных int.Почему мне нужно использовать T& вместо T в качестве аргумента шаблона?И зачем мне промежуточная функция, которая определяет i как значение?

class DataClass
{

};

template <typename T>
bool func(T& data, int& i) {
  i = 1;
  cout << "it worked!" << endl;
}

// I would like to remove this function
template <typename T>
bool func(T& data, int&& i) {
  return func(std::forward<T&>(data), std::forward<int&>(i));
}

template <typename T>
bool func(T& data) {
  // Why doesn't this line work?
  // return func(std::forward<T>(data), std::forward<int>(0));
  return func(std::forward<T&>(data), 0);
}

int main(int argc, char ** argv)
{
  DataClass d;
  func<DataClass>(d);
  return 0;
}

1 Ответ

1 голос
/ 13 мая 2019

Вам вообще не нужно std::forward здесь.За исключением int&& i во второй перегрузке, все ваши параметры объявлены как неконстантные lvalue-ссылки, поэтому вы не можете передать rvalue ни одной из них.А в перегрузке int&&, если вы хотите вызвать функцию lvalue из функции rvalue, вы можете просто назвать параметр i, потому что имя всегда является lvalue.

template <typename T>
bool func(T& data, int& i) {
  i = 1;
  cout << "it worked!" << endl;
}

template <typename T>
bool func(T& data, int&& i) {
  return func(data, i);
}

template <typename T>
bool func(T& data) {
  return func(data, 0);
}

Если выЕсли вы хотите удалить функцию, обратите внимание, что на самом деле int& делает что-то по-другому: она меняет i на 1. Технически также перегрузка rvalue, но то, что было передано как rvalue, обычно следует игнорироватьпосле этого момента вызывающие абоненты должны рассчитывать только на func(T&, int&&), чтобы распечатать сообщение на cout.И чтобы взять int, который не является lvalue ... просто возьмите int.

template <typename T>
bool func(T& data, int& i) {
  i = 1;
  cout << "it worked!" << endl;
}

template <typename T>
bool func(T& data, int i=0) {
  return func(data, i); // effect on i is ignored.
}

// Okay to pass a const int?
template <typename T>
bool func(T&, const volatile int&&) = delete;

Этот третий удаленный шаблон сохраняет одно поведение вашего исходного кода, хотя не ясно, если вына самом деле хотите такое поведение или нет.В функции

void test() {
    DataClass d;
    const int n = 5;
    func(d, n);
}

... исходный код не удалось бы скомпилировать, поскольку const int lvalue не может связываться ни с int&, ни с int&&.Но изменение параметра просто int позволило бы скомпилировать test, сделав копию n равной обычному параметру int.Тогда изменение этого int i просто отменяется, даже если вы дали n функции.Удаленный шаблон лучше подходит для const int lvalue n, поэтому он может не скомпилировать test.Если вам нужно поведение, в котором func(d, n) является действительным, но не влияет на n, просто удалите этот удаленный шаблон.

...