Reputation: 1579
Assume I have the following template:
template<typename T>
struct S
{
typedef decltype(foo(T{})) TypeThatSomeFooFunctionReturns;
typedef decltype(*TypeThatSomeFooFunctionReturns{}) TypeOfDereferenceOfWhateverFooReturns;
...
};
Now, this works just fine if the type T has a default constructor and if whatever "foo(T)" returns also has a default constructor.
But how would I write the template, if I don't want that assumption but also support any type T regardless of whether it (or any "foo(T)") provides constructors? (As I never construct these objects by myself anyway)
One clumsy solution that springs into my mind is to force the users of struct S to provide a template specialization for its arguments, basically unrolling the work of finding the correct type to whoever uses S:
template<typename T> struct S_Def { };
// User needs to provide these for each type
template<> struct S_Def<MyType> { typedef int* ReturnOfFoo; typedef int& DerefOfReturnOfFoo; };
template<typename T>
struct S
{
typedef S_Def<T>::ReturnOfFoo TypeThatSomeFooFunctionReturns;
typedef S_Def<T>::DerefOfReturnOfFoo TypeOfDereferenceOfWhateverFooReturns;
...
};
I'd like to avoid that burden.
Is there any other way to tell the compiler to just take whatever type any reachable function "foo(T)" returns for the typedef and then whatever any dereference operator on that type would return?
If not, are there reasons why? (Is it impossible? I'd be fine if ambiguity lead to a compile error.. Or too hard for the compiler to find?)
Thanks, Imi.
Upvotes: 2
Views: 436
Reputation: 218098
You might use std::declval
, and type_traits to modify the type:
template<typename T>
struct S
{
using TypeThatSomeFooFunctionReturns = decltype(foo(std::declval<T>()));
using TypeOfDereferenceOfWhateverFooReturns =
std::remove_pointer_t<decltype(foo(std::declval<T>()))>;
// ...
};
Upvotes: 7