Это продолжение этого (более общего) вопроса: предыдущий вопрос. Частичный ответ на данный вопрос дан здесь: частичный ответ на настоящий вопрос.
Я заинтересован в явной специализации возвращаемого типа на основе аргумента шаблона. Хотя приведенный выше ответ дает решение проблемы, я считаю, что существует более элегантный способ решения проблемы с использованием методов 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? Если нет, то почему нет?
Вы можете расширить идею вспомогательного шаблонного класса и поместить в него практически все. Это не совсем красиво для тех, кто должен написать специализацию, но это очень удобно для пользователя, который может просто позвонить 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
(с лучшим именем) в полном объеме.