Reputation: 39174
I am trying to figure out what's wrong with this code:
#include <string>
struct Bar
{
using Deduced = typename std::string;
};
class Test
{
template<typename Foo>
auto Func() -> decltype(Foo::Deduced)
{
return Foo::Deduced();
}
};
int main()
{
Test t;
std::string ret = t.template Func<Bar>();
}
I am refactoring a class where Func
return type was declared as a template class parameter of Test
class, but I would like to change this to work as a member template parameter.
Is this possible? If yes, anyone could suggest me the right syntax?
Upvotes: 1
Views: 67
Reputation: 311038
In this alias declaration
using Deduced = typename std::string;
the keyword typename
is redundant. Just write
using Deduced = std::string;
The template function Func
is a private member function of the class Test
. You need to make it public.
The decltype
specifier expects an expression. You should write at least like
auto Func() -> typename Foo::Deduced
Upvotes: 2
Reputation: 119239
Remove the decltype
.
decltype
gives the type of an expression. But Foo::Deduced
is already a type, so you can't apply decltype
to it. You simply want to refer to that type itself. So all you have to do is write Foo::Deduced
.
However, in some contexts, you need to prefix it with typename
to tell the compiler that it's really a type. In C++20, you need typename
in return Foo::Deduced()
but you don't need it in the trailing return type. Prior to C++20, it was needed in both places. Thus your code could be rewritten like so:
template<typename Foo>
auto Func() -> Foo::Deduced
{
return typename Foo::Deduced();
}
Or a deduced return type could be used:
template<typename Foo>
decltype(auto) Func() // notice no trailing return type
{
return typename Foo::Deduced();
}
Upvotes: 5