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
.