Reputation: 785
The following is a (over-)simplified excerpt of a real C++14 application. For reasons of maintainability I did not want to specify the return type of foo()
explicitly. I am aware that C++14 can deduce the return type of functions auto
matically. But the real application required the return type inside the function. So I needed it at hand.
The following code snippet compiles (g++ 4.9.2) fine:
#include <type_traits>
#include <iostream>
#include <string>
//auto foo (std::wstring &s) -> std::remove_reference <decltype (s)>::size_type
auto foo (std::wstring &s) -> decltype (s.length ())
{
return s.length ();
}
int main ()
{
std::wstring s {L"hello world"};
std::cout << foo (s) << "\n";
return 0;
}
But if I use the "commented-out" version of the function declaration I get the following diagnostics:
foo.cpp:5:69: error: ‘size_type’ in ‘struct std::remove_reference<std::basic_string<wchar_t>&>’ does not name a type
auto foo (std::wstring &s) -> std::remove_reference <decltype (s)>::size_type
^
What's wrong? Isn't std::wstring::size_type
a type?
Doesn't std::remove_reference
convert std::basic_string<wchar_t>&
into a plain std::wstring
?
Upvotes: 2
Views: 2663
Reputation: 22552
std::remove_reference
does not have a size_type
member, std::wstring
has. You can access std::wstring
with std::remove_reference<decltype(s)>::type
. Therefore, what you really need for your return type is:
std::remove_reference <decltype (s)>::type::size_type
Since you are using C++14, you can use std::remove_reference_t
instead, which is an alias template shortcut introduced for readability:
std::remove_reference_t <decltype (s)>::size_type
EDIT: As noted by @Cassio in the comments, since you are using C++14, you may as well let the function deduce the return type with auto
which will automatically strip the reference:
auto foo (std::wstring &s)
{
return s.length ();
}
That said, you should really think about when you really want to do it. Many people prefere to have an explicit return type when it makes sense.
Upvotes: 5