在没有初始化的情况下声明变量时的 C++ 自动类型推导

C++ auto type deduction when declaring variables without initialisation

我真的很喜欢 C++ 中的自动类型推导,我可以从一个函数中得到任意复杂的 return 类型,而不用担心调用函数时的类型是什么。

换句话说,类似于:

std::vector<std::map<std::string, std::string>> getCollection() { ... }
auto myMapArray = getCollection();

然而,这似乎只有在编译器可以推导出类型时才有效,例如当它从函数初始化时。

我经常发现自己处于这样一种情况,我只想要一个正确类型的默认构造变量(通常是 class 成员变量),这让我很痛苦:

std::vector<std::map<std::string, std::string>> getCollection();
std::vector<std::map<std::string, std::string>> m_collection;

在这种情况下。但我知道没有其他方法可以避免使用长类型名称,除了使用 typedef 或更现代的 using:

typedef std::vector<std::map<std::string, std::string>> VecOfMaps;
using VecOfMaps = std::vector<std::map<std::string, std::string>>;
:
VecOfMaps m_collection;

似乎允许变量的类型推导是有用的,就好像它是从函数 returned 的东西,例如 with:

std::vector<std::map<std::string, std::string>> getCollection() { ... }
auto m_collection = asif(getCollection);

您不需要提供参数,因为所有重载都需要 return 相同的类型。所以我的问题真的是:

关于您的评论:

It appears it would be useful to allow type deduction of a variable as if it were something returned from a function, such as with:

std::vector<std::map<std::string, std::string>> getCollection() { ... }
auto m_collection = asif(getCollection);

我觉得 asif() 听起来有点像 decltype()

在这种情况下,需要 return 类型的函数,因此它应该是

decltype(getCollection()) m_collection;

我必须承认,我对 decltype() 在日常业务中的实际使用并没有那么丰富的经验,因此(出于好奇)摆弄了一下自己,最后得出:

#include <iostream>
#include <map>
#include <string>
#include <vector>

auto func() { return std::vector<std::map<std::string, std::string>>(); }

struct Class {
  typedef decltype(func()) VarType;
  VarType var;
};

int main()
{
  Class obj;
  std::cout << "type of Class::var: " << typeid(obj.var).name() << '\n';
}

其输出为:

type of Class::var: St6vectorISt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_St4lessIS6_ESaISt4pairIKS6_S6_EEESaISD_EE

Live Demo on coliru

到目前为止,还不错。


Can I do a decltype(fn()) variable; without a type alias?

#include <iostream>
#include <map>
#include <string>
#include <vector>

auto func() { return std::vector<std::map<std::string, std::string>>(); }

struct Class {
  decltype(func()) var;
};

int main()
{
  Class obj;
  std::cout << "type of Class::var: " << typeid(obj.var).name() << '\n';
}

输出:

type of Class::var: St6vectorISt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_St4lessIS6_ESaISt4pairIKS6_S6_EEESaISD_EE

Live Demo on coliru

我必须承认,这是链接的 decltype() 文档中的示例之一,它让我确定了这一点。

此外,我想提一下 decltype() 是(类似于 sizeof)一个编译时仅类型评估。因此,即使根本没有 func() 的实现,它也能工作:

#include <iostream>
#include <map>
#include <string>
#include <vector>

std::vector<std::map<std::string, std::string>> func();

struct Class {
  decltype(func()) var;
};

int main()
{
  Class obj;
  std::cout << "type of Class::var: " << typeid(obj.var).name() << '\n';
}

输出:

type of Class::var: St6vectorISt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES6_St4lessIS6_ESaISt4pairIKS6_S6_EEESaISD_EE

Live Demo at coliru


It looks like I can do the former but I want to make sure it's a standard thing and not just a gcc extension.

据我所知,decltype() 实际上是一个 C++ 标准特性(因为 C++11 和 cppreference.com 中提到的事实将算作 "proof"对我来说)。

除此之外,我用最后一个样本来检查

  • 叮当声 10.0.0 -std=c++11
  • gcc 10.1 -std=c++11
  • msvc v19.24 /std:c++14/std:c++11 不是可用选项。)

所有人都在 CompilerExplorer 上通过了这项检查。