Home > Blockchain >  Is there a way to specify a function's return type as a template parameter
Is there a way to specify a function's return type as a template parameter

Time:03-07

I have a function template that I'm writing, which deals with a lot of objects of type N (which can only be a couple of different things, but there's a lot of logic in this template which I don't want to duplicate in separate functions). In several places in this function, I also have declarations like auto somevar = SomeFunction(someobject); where someobject is of type N and SomeFunction is overloaded, returning different types based on the type of someobject — but, importantly, no overload of SomeFunction returns an N. Now, instead of a plain variable, I want to have a container (specifically, std::unordered_set) whose elements are of the type returned by SomeFunction, but I'm having trouble figuring out how to write the necessary class template parameter.

I've tried std::unordered_set<auto> hoping the compiler can deduce the type from what elements it is initialized with, but that didn't work. I tried std::unordered_set<SomeFunction(someobject)>, std::unordered_set<SomeFunction(someobject)::type>, and std::unordered_set<typeof(SomeFunction(someobject))>, but those didn't work either. It seems the C standard lacks a way to express this directly.

CodePudding user response:

What I did is write a class template some_transform that can be used like this std::unordered_set<some_transform<N>::Type>, where some_transform essentially maps the given type N to the corresponding return value of SomeFunction. The actual mapping is defined in specializations of the template class some_transform, so it looks like this:

template <typename N> class some_transform
{
public:
    typedef N Type; // this identity mapping is not useful, except so the IDE expects a member type by this name
};
template <> class some_transform<A>
{
public:
    typedef X Type;
};
template <> class some_transform<B>
{
public:
    typedef Y Type;
};

Using this class template, some_transform<A>::Type resolves to type X, and some_transform<B>::Type resolves to type Y. So the expression some_transform<N>::Type can be used in template parameters where a type is expected, within a template with parameter N, where the actual type parameter (X or Y) depends on whether N is A or B. I just have to make sure this class correctly maps the types given to SomeFunction (as mentioned in the question) to the corresponding types returned by SomeFunction.

Note that the identifier Type isn't special, and can by anything; in fact, the some_transform<N> class can have multiple member types, e. g. IndexType and HashType; and a name for the class might be better as something like TypeMap, where the name of the member type indicates what transformation or mapping is done.

CodePudding user response:

As some others have said, you should use decltype. So you'll write std::unordered_set<decltype(SomeFunction(someobject))> as your return type.

Sidenote: You might find mention online of typeof which the GCC compiler added support for before C 11 added decltype. typeof works in the same way as decltype but isn't part of the C standard and so isn't supported by non-GCC compilers. For this reason you should always use decltype instead of typeof.

  • Related