C++声明变量时自动类型推断而不初始化
C++ auto type deduction when declaring variables without initialisation
我实际上非常喜欢C++中的自动类型推导,我可以从函数中获得任意复杂的返回类型,但在调用函数时不必担心类型是什么。
换句话说,像这样:
std::vector<std::map<std::string, std::string>> getCollection() { ... }
auto myMapArray = getCollection();
但是,这似乎仅在编译器可以推断类型时才有效,例如从函数初始化时。
我经常发现自己的情况是,我只想要一个正确类型的默认构造变量(通常是类成员变量(,这让我很痛苦:
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;
似乎允许变量的类型推导很有用,就好像它是从函数返回的东西一样,例如:
std::vector<std::map<std::string, std::string>> getCollection() { ... }
auto m_collection = asif(getCollection);
不需要提供参数,因为所有重载都需要返回相同的类型。所以我的问题真的是:
- 有没有比类型别名更好的方法来做到这一点?
asif
解决方案是否有任何明显的缺点(它必须允许模板化功能,但这应该只是一个次要的扩展(?
关于您的评论:
似乎允许变量的类型推导很有用,就好像它是从函数返回的东西一样,例如:
std::vector<std::map<std::string, std::string>> getCollection() { ... } auto m_collection = asif(getCollection);
在我看来,asif()
听起来有点像decltype((。
在这种情况下,它是必需的函数的返回类型,因此它应该是
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
科里鲁的现场演示
目前为止,一切都好。
我可以在没有类型别名的情况下执行
decltype(fn()) variable;
吗?
#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
科里鲁的现场演示
我必须承认,这是链接的 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
科里鲁的现场演示
看起来我可以做前者,但我想确保它是一个标准的东西,而不仅仅是一个 gcc 扩展。
据我所知,decltype()
实际上是一个C++标准功能(自 C++11 以来,cppreference.com
中提到的事实对我来说算作"证据"(。
除此之外,我使用最后一个样本来检查它
- 叮当 10.0.0
-std=c++11
- GCC 10.1
-std=c++11
- MSVC v19.24
/std:c++14
(/std:c++11
不是可用的选项。
所有人都通过了编译器资源管理器上的此检查。
- 无法使用类型 'const char *' 的左值初始化类型 'char *' 的成员子对象
- "const wchar_t *" 类型的值不能用于初始化类型 "const PWSTR" 的实体
- Visual Studio C++:不能使用类型为 "const wchar_t *" 的值来初始化类型为 "TCHAR *" 的实体
- 为什么我总是收到此错误:从类型为"农场动物"的右值初始化类型的非常量引用无效|
- 无法使用类型为"结构节点 *"的左值初始化类型为"结构节点 *"的参数
- C++ 解决方法:"从类型"B*"的表达式初始化类型"C*&"的引用无效"
- 零初始化类型
- 回调方法显示错误,类型为"void(*)"的值不能用于初始化类型的实体
- C++ 重载和覆盖 - 无法使用类型的右值初始化类型的参数
- 类型值不能用于初始化类型实体
- 无效初始化类型的 BinaryNode *& 的非常量引用
- 从类型 'Matrix&' 的右值初始化 类型的非 const 引用无效 'Matrix'
- 无法汇总初始化类型结构的变量,其中包含在类模板中的位字段成员
- 直接或通过构造函数初始化类型的类
- 无法使用 'Shape *' 类型的左值初始化类型 'Shape Shape::*' 的返回对象
- C++:从类型"int*"的表达式初始化类型"const int*&"的引用无效
- 从类型为"矩阵"的右值初始化类型为"矩阵"的非常量引用无效
- 无法使用类型 'const char [X]' 的左值初始化类型 'const signed char *' 的成员子对象
- C 我可以用双重初始化类型浮点的变量
- 无法识别初始化类型