C ++: частичная специализация функций для void запрещена - альтернативное решение? - PullRequest
4 голосов
/ 12 августа 2011

Мне кажется, я уже понимаю, почему шаблоны частичных функций считаются запутанными и ненужными и поэтому не допускаются стандартом C ++.Однако я был бы признателен за помощь в перефразировании следующей функции без частичной специализации.Кстати, функция является членом неспецифического класса:

template <typename IMPL, typename RET>
RET call (functor <IMPL> func, 
          IMPL * impl)
{ 
  return func.call (impl);
}

template <typename IMPL>
void call <IMPL, void_t> (functor <IMPL> func, 
                          IMPL * impl) 
{ 
  func.call (impl);
}

Проблема в том, что я не могу перегрузить тип возвращаемого значения функции.Кроме того, имя типа, на котором я хочу специализироваться, не используется в качестве параметра функции - еще одна причина, по которой перегрузка не помогает.Да, я мог бы ввести фиктивный параметр, чтобы вызвать перегрузку, но это ужасно, не так ли?

Наконец, почему, черт возьми, не «пустота» типа в C ++?Это сделало бы вещи намного более последовательными ... Но я, вероятно, упускаю полную картину ...

Ответы [ 5 ]

7 голосов
/ 12 августа 2011

Я считаю, что, во-первых, если у вас есть функция, которая возвращает void, то вполне допустимо return выражение void, например, вызов другой функции, которая возвращает void, и, во-вторых, void - это полный тип в C ++, и вы можете передавать его в шаблоны сколько угодно.

2 голосов
/ 12 августа 2011

Во-первых,

template <typename IMPL, typename RET>
RET call (functor <IMPL> func, 
          IMPL * impl)
{ 
  return func.call (impl);
}

действительно должно быть

template <typename RET, typename IMPL>
RET call (functor <IMPL> func, 
          IMPL * impl)
{ 
  return func.call (impl);
}

(я инвертировал RET и IMPL в списке аргументов шаблона), чтобы вы могли вызывать функцию как

call<int>(f, impl);

вместо необходимости набирать

call<impl_type, int>(f, impl);

Действительно, компилятор не может вывести RET, поэтому вы должны предоставить его самостоятельно.

Во-вторых, вам не нужно перегружать void, поскольку нормально возвращать выражение void. Если вы хотите, вы можете добавить перегрузку:

template <typename IMPL>
void call(functor<IMPL> func, IMPL* impl)

и используйте call(f, impl) при вызове этой перегрузки.

Если у вас есть доступ к C ++ 0x, рассмотрите возможность использования decltype.

2 голосов
/ 12 августа 2011

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

В вашем случае, однако, я думаю, вы должны использовать void в качестве типа возврата, как отмечено в других ответах.

2 голосов
/ 12 августа 2011

Если в вашем шаблонном классе functor уже есть typedef для RET, вы можете сделать это вместо этого:

template <typename IMPL>
typename functor<IMPL>::RET call (functor <IMPL> func, 
          IMPL * impl)
{ 
  return func.call (impl);
}

и не заморачиваться с перегрузкой. Кроме того, какой компилятор вы используете? Все компиляторы, соответствующие стандарту, позволяют возвращать результат функции void из функции void.

1 голос
/ 12 августа 2011

Вы можете сделать это с помощью перегрузки функции:

template <typename IMPL, typename RET>
RET call (functor <IMPL> func, 
          IMPL * impl)
{ 
  return func.call (impl);
}

template <typename IMPL>
void call (functor <void_t> func, void_t * impl) 
{ 
  func.call (impl);
}

Кроме того, void является типом в C ++; что заставляет вас думать, что это не так?

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