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?
CodePudding user response:
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();
}
CodePudding user response:
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
