C++ явная специализация возвращаемого типа шаблона

Это продолжение этого (более общего) вопроса: предыдущий вопрос. Частичный ответ на настоящий вопрос дается здесь: частичный ответ на настоящий вопрос.

Я заинтересован в явной специализации возвращаемого типа на основе аргумента шаблона. Хотя приведенный выше ответ дает решение проблемы, я считаю, что существует более элегантный способ решения проблемы с использованием методов C++11/14:

template<int N> auto getOutputPort2();
template<> auto getOutputPort2<0>();
template<> auto getOutputPort2<1>();

template<>
auto getOutputPort2<0>()
{
    return std::unique_ptr<int>(new int(10));
}

template<>
auto getOutputPort2<1>()
{
    return std::unique_ptr<string>(new string("asdf"));
}

Приведенный выше код компилируется и работает, как и ожидалось, используя gcc 4.8.3 (с флагом -std= C++0x). Тем не менее, он выдает следующее предупреждение:

getOutputPort2 функция использует auto спецификатор типа без конечного возвращаемого типа.

Насколько я понимаю, это станет частью стандарта C++14. Однако есть ли способ реализовать описанную выше функциональность в C++11? Можно decltype использоваться здесь?


РЕДАКТИРОВАТЬ. Следуя комментариям ниже, я также хотел бы задать дополнительный вопрос. Является ли приведенный выше код действительным с точки зрения стандарта C++14? Если нет, то почему нет?

1 ответ

Решение

Вы можете расширить идею вспомогательного класса шаблона и поместить в него практически все. Это не совсем красиво для тех, кто должен написать специализацию, но это очень удобно для пользователя, который может просто позвонить f<0>, f<1>и т.д. Это действительно не нужно decltype, но decltype действительно делает это немного легче писать.

template <int N>
struct f_impl;

template <int N>
decltype(f_impl<N>::impl()) f()
{ return f_impl<N>::impl(); }

template <> struct f_impl<0> {
  static int impl() { return 1; }
};

template <> struct f_impl<1> {
  static const char *impl() { return " Hello, world!"; }
};

int main() {
  std::puts(f<1>() + f<0>());
}

Вы можете сделать его более управляемым с помощью макросов: вместо

template <> struct f_impl<1> {
  static const char *impl() { return " Hello, world!"; }
};

Вы могли бы написать что-то вроде

#define DEFINE_F(N, Result)      \
  template <> struct f_impl<N> { \
    static Result impl();        \
  };                             \
  Result f_impl<N>::impl()

DEFINE_F(1, const char *) {
  return " Hello, world!";
}

но я не уверен, что это лучше, чем просто писать f_impl (с лучшим именем) в полном объеме.

Другие вопросы по тегам