C++:使用 decltype 派生函数 return 类型

C++: Deriving a function return type using decltype

以下是真实 C++14 应用程序的(过度)简化摘录。出于可维护性的原因,我不想明确指定 foo() 的 return 类型。我知道 C++14 可以自动推导 return 类型的函数 auto。但是真正的应用程序需要函数内部的 return 类型。所以我手边需要它。

以下代码片段可以正常编译 (g++ 4.9.2):

#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;
    }

但是如果我使用 "commented-out" 版本的函数声明,我会得到以下诊断信息:

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
                                                                    ^

怎么了? std::wstring::size_type 不是一个类型吗? std::remove_reference 不会将 std::basic_string<wchar_t>& 转换为普通的 std::wstring 吗?

std::remove_reference 没有 size_type 成员,std::wstring 有。您可以使用 std::remove_reference<decltype(s)>::type 访问 std::wstring。因此,您的 return 类型真正需要的是:

std::remove_reference <decltype (s)>::type::size_type

由于您使用的是 C++14,因此可以使用 std::remove_reference_t 代替,这是为了提高可读性而引入的别名模板快捷方式:

std::remove_reference_t <decltype (s)>::size_type

编辑: 正如@Cassio 在评论中指出的那样,由于您使用的是 C++14,您不妨让函数推导 return 类型使用 auto 将自动删除引用:

auto foo (std::wstring &s)
    {
    return s.length ();
    }

也就是说,你真的应该考虑 when you really want to do it。许多人更喜欢在有意义的情况下使用明确的 return 类型。