This is a follow up on this (more general) question: previous question. A partial answer to the present question is given here: partial answer to the present question.
I am interested in explicit specialisation of the return type based on the template argument. While the answer presented above provides a solution to the problem, I believe that there is a more elegant way of solving the problem using C++11/14 techniques:
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"));
}
The code above compiles and works as expected using gcc 4.8.3 (with -std=c++0x flag). However, it issues the following warning:
getOutputPort2
function usesauto
type specifier without trailing return type.
From my understanding this will become part of the C++14 standard. However, is there a way of implementing the functionality above in C++11? Can decltype
be used here?
EDIT. Following the comments below, I would also like to ask an additional question. Is the code above valid from the perspective of the C++14 standard? If not, why not?
You can extend the idea of a helper template class, and put pretty much everything in there. It's not exactly pretty for whoever has to write the specialisations, but it's very convenient for the user, who can just call f<0>
, f<1>
, etc. It doesn't really need decltype
, but decltype
does make it quite a bit easier to write.
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>());
}
You might be able to make it a bit more manageable with macros: instead of
template <> struct f_impl<1> {
static const char *impl() { return " Hello, world!"; }
};
you could write something along the lines of
#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!";
}
but I'm not convinced it's an improvement over just writing out f_impl
(with a better name) in full.