hermannk
hermannk

Reputation: 785

C++: Deriving a function return type using decltype

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 automatically. 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

Answers (1)

Morwenn
Morwenn

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

Related Questions