2016-08-01 1 views
5

У меня есть, казалось бы, простой вопрос, который я не знаю, как решить.Перегрузка шаблона (справочная и неосновная версия)

Представьте себе следующий метод шаблона

template<typename T> void Add(T& var); 

где специализации могут добавить что-то в контейнер (вроде). Я могу передать POD или более сложные типы, такие как strings, и именно поэтому я передаю T в качестве ссылки.

Проблема с этим состоит в том, что всякий раз, когда я хочу позвонить Добавить (...) с результатом другого способа, как:

Add(MethodThatReturnsAnInt()); 

Это не будет работать и временная переменная необходима, чтобы удерживать результат MethodThatReturnsAnInt().

Есть ли способ перегрузки Add, чтобы у меня была эталонная версия для передачи и без ссылки?

template<typename T> void Add(T& var); 
template<typename T> void Add(T var); 

бы std::enable_if никакой пользы в этой ситуации?

+0

Читайте и узнайте о [ссылках на rvalue] (http://en.cppreference.com/w/cpp/language/reference). –

+0

Google _forwarding reference_. Ваша ситуация и результирующий вопрос были настолько распространены, что они добавили для него языковую функцию. ;-) Это фундаментальная особенность C++ 11 и, вероятно, уже достаточно долгое время. –

+0

Какую проблему вы на самом деле пытаетесь решить? Что делает 'Add()' do? – Barry

ответ

6

Если у вас есть C++ 11 компилятора, вы могли бы использовать (Universal Reference)пересылку ссылку:

template<typename T> void Add(T&& var) {} 

int MethodThatReturnsAnInt() { return 42; } 

int main() 
{ 
    int a = MethodThatReturnsAnInt(); 

    Add(a);      // lvalue passed: void Add(int& var) takes lvalue reference 
    Add(MethodThatReturnsAnInt()); // rvalue passed: void Add(int&& var) takes rvalue reference 
} 

T&& не ссылка Rvalue в этом примере. В контексте вывода типа T&& имеет особое значение. T зависит от экспрессии переданной функции Add() следующим образом:

  • Если выражение является именующего (например: a) типа E, то Т выводится на E&.

  • Если выражение является Rvalue (например: значение, возвращаемое функцией) типа E, то Т выводится на E и var будет иметь тип E&&.

+0

Как это отличается от того, что сказал @SamVarshavchik (кроме того, что вы используете старомодное имя _universal reference_)? Кроме того, пример выглядит как-то неправильно и вводит в заблуждение. – skypjack

+0

Второй вызов - это 'Add (int && var)', а не 'Add (int var)'. Это может быть одинаково для 'int', но не для более сложного класса. – Holt

+2

@skypjack sam name сбросил термин, который вы могли бы использовать для google и решить проблему, используя помощь в другом месте. Серджи написал ответ, который решает проблему здесь. – Yakk

2

Если ваш компилятор еще не поддерживает C++ 11, вам необходимо будет обновить свой компилятор, а затем использовать ссылку пересылки &&.

Смежные вопросы