Обработка ссылок в шаблонах C ++ - PullRequest
2 голосов
/ 16 декабря 2009

В настоящее время у меня есть шаблон функции, использующий ссылку, которая делает что-то по существу эквивалентное:

template <typename T>
void f(T& t)
{
   t = T();
}

Теперь я могу позвонить:

int a;
f(a);

Для инициализации моей переменной a. Я даже могу сделать:

std::vector<int> a(10);
f(a[5]);

Однако это не удастся:

std::vector<bool> a(10);
f(a[5]);

Причина в том, что a[5] возвращает объект со ссылочной семантикой, но не со ссылкой. Поэтому мне нужно уметь написать:

template <typename T>
void f(T a)
{
  a = T();
}

Но если я добавлю этот новый шаблон и попытаюсь скомпилировать первый пример (с помощью int), я получу следующую ошибку:

test_multi_tmpl.cc: In function ‘int main()’:
test_multi_tmpl.cc:20: error: call of overloaded ‘f(int&)’ is ambiguous
test_multi_tmpl.cc:6: note: candidates are: void f(T&) [with T = int]
test_multi_tmpl.cc:12: note:                 void f(T) [with T = int]

Есть идеи, как это решить? Я не хотел бы перегружать f только для std::vector<bool>::reference, поскольку эта конструкция может появляться в других местах ...

Ответы [ 4 ]

4 голосов
/ 16 декабря 2009

Я думаю, специализировать f для std::vector<bool>::reference - ваш единственный выбор.

Обратите внимание, что использование std::vector<bool>, вероятно, является плохой идеей (специализация std::vector<bool> не рекомендуется для будущих версий языка c ++), поэтому вы можете просто использовать std::deque<bool>.

1 голос
/ 16 декабря 2009

Я не уверен, знаете ли вы уже об этом ...

Специализация std :: vector , а не , действительно контейнер STL, потому что не соответствует необходимым требованиям. В частности, невозможно создать прокси-контейнеры, которые удовлетворяют концепции STL из-за ссылочной семантики (вы не можете подделать ссылку). Проверьте эту статью для получения дополнительной информации. (Кроме того, как уже упоминалось в Autopulated, должна существовать директива компилятора, обеспечивающая контроль над std :: vector в будущем стандарте C ++.)

Простой обходной путь, который может решить вашу проблему, - перегрузить функцию f для этого конкретного типа (и других, если они появляются и их немного). Обратите внимание, что это перегрузка и , а не и специализация . Вы также можете проверить это для , почему бы не специализировать шаблоны функций .


void f(std::vector<bool>::reference t)
{
  /* ... */
}
1 голос
/ 16 декабря 2009

Есть два способа сделать это, один, как вы предлагаете, специализироваться на std::vector<bool>::reference. Другой - с использованием диспетчеризации типов.

template <class T>
void f (T& t) {
  f_impl(t, is_reference_wrapper_type<T>());
}

template <class T>
void f_impl(T& t, mpi::false_) {
  t = T();
}

template <class T>
void f_impl(T& t, mpi::true_) {
  // do nothing, or voodoo here
}

Обратите внимание, что приведенный выше код не проверен, и в этой ситуации могут быть более сложные средства диспетчеризации на основе признака - или набора признаков.

Это также означает, что вам нужно реализовать is_reference_wrapper_type следующим образом:

template <class T>
struct is_reference_wrapper_type : mpi::false_ {};

template <>
struct is_reference_wrapper_type<std::vector<bool>::reference> : mpi::true_ {};
0 голосов
/ 16 декабря 2009

Используя черты или специализацию шаблонов, все заработает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...