在没有初始化的情况下声明变量时的 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 相同的类型。所以我的问题真的是:
- 有没有比输入别名更好的方法来做到这一点?
asif
解决方案是否有任何明显的缺点(它必须允许模板化函数,但这应该只是一个小的扩展)?
关于您的评论:
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
到目前为止,还不错。
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
我必须承认,这是链接的 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
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 上通过了这项检查。
我真的很喜欢 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 相同的类型。所以我的问题真的是:
- 有没有比输入别名更好的方法来做到这一点?
asif
解决方案是否有任何明显的缺点(它必须允许模板化函数,但这应该只是一个小的扩展)?
关于您的评论:
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
到目前为止,还不错。
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
我必须承认,这是链接的 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
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 上通过了这项检查。