std::initializer_list的类型推断
type inference for std::initializer_list
如果我这样写
std::vector<std::string> v{"one","two","three"};
关联的std::initializer_list
模板推断的类型是什么?换句话说,当char *
字符串字面值转换为std::string
?
最好声明为
std::vector<std::string> v{std::string("one"),
std::string("two"),
std::string("three")};
来避免与所涉及的模板的类型推导机制相关的问题?
更新:回答你关于类型推断的问题:vector<string>
的初始化列表构造函数接受一个initializer_list<string>
。它没有模板化,所以在类型推断方面没有发生任何事情。
原始答:
首先,编译器只看到初始化项列表 {"one","two","three"}
,这只是一个初始化项列表,还不是std::initializer_list
类型的对象。
然后尝试找到vector<string>
的合适构造函数来匹配该列表。如何做到这一点是一个有点复杂的过程,如果你对确切的过程感兴趣,你最好查阅一下标准本身。
因此,编译器决定从初始化列表创建std::initializer_list<string>
的实际对象,因为从char*
到std::string
的隐式转换使得这成为可能。
另一个可能更有趣的例子:
std::vector<long> vl1{3};
std::vector<string> vs1{3};
std::vector<string> vs2{0};
这些是做什么的?
第一行比较简单。初始化列表
{3}
可以转换为类似于上面{"onm", "two", "three"}
示例的std::initializer_list<long>
,因此您得到一个具有单个元素的向量,其值为3。第二行不同。它构造了一个包含3个空字符串的向量。为什么?因为初始化列表
{3}
无法转换为std::initializer_list<string>
,所以"普通"构造函数std::vector<T>::vector(size_t, T = T())
开始并给出三个默认构造的字符串。这个应该和第二个差不多,对吧?它应该给出一个空向量,换句话说,没有默认构造的字符串。错! 。
0
可以被视为空指针常量,并验证std::initializer_list<string>
。只是这次列表中的单个字符串是由空指针构造的,这是不允许的,所以你会得到一个异常。
没有类型推断,因为vector只提供了一个带初始化列表的完全专门化的构造函数。我们可以间接添加一个模板来进行类型演绎。下面的示例显示了std::initializer_list<const char*>
是vector构造函数的无效实参。
#include <string>
#include <vector>
std::string operator"" _s( const char* s, size_t sz ) { return {s, s+sz}; }
template<typename T>
std::vector<std::string> make_vector( std::initializer_list<T> il ) {
return {il};
}
int main() {
auto compile = make_vector<std::string>( { "uie","uieui","ueueuieuie" } );
auto compile_too = make_vector<std::string>( { "uie"_s, "uieui", "ueueuieuie" } );
//auto do_not_compile = make_vector( { "uie","uieui","ueueuieuie" } );
}
现场演示
From http://en.cppreference.com/w/cpp/language/string_literal:
无前缀字符串字面值的类型为
const char[]
所以事情是这样的:
#include <iostream>
#include <initializer_list>
#include <vector>
#include <typeinfo>
#include <type_traits>
using namespace std;
int main() {
std::cout << std::boolalpha;
std::initializer_list<char*> v = {"one","two","three"}; // Takes string literal pointers (char*)
auto var = v.begin();
char *myvar;
cout << (typeid(decltype(*var)) == typeid(decltype(myvar))); // true
std::string ea = "hello";
std::initializer_list<std::string> v2 = {"one","two","three"}; // Constructs 3 std::string objects
auto var2 = v2.begin();
cout << (typeid(decltype(*var2)) == typeid(decltype(ea))); // true
std::vector<std::string> vec(v2);
return 0;
}
http://ideone.com/UJ4a0i - std::list 模板是否需要其实例类型中的复制构造函数(或等效项)?
- C++类模板类型 std::list
- 获取迭代器在基类型 "intrusive doubly linked list" 的指针字典中的位置
- C++ - 错误:'list'没有命名类型(将对象列为类中的成员变量)
- 'list::list'命名构造函数,而不是类型
- 为什么std::list可以有一个T类型的分配器
- 在std::list中就地创建自定义类型对象
- QPlainTextEdit dragEnterEvent 不接受 text/uri-list mime 类型
- 错误:"模板<类_Tp、类_Alloc>类 std::list"的模板参数列表中参数 1 的类型/值不匹配
- sizeof(std::list<T>) 可以因不同类型的 T 而异吗?
- 您将如何为 std::list<std::string> 创建一个类型映射,以在<String> List in C++ 中为 Java 在 SWIG 中创建?
- 我读过std::list很糟糕。有人可以将其与.网的名单<>类型?我从 C 来到C++#
- 如何编写一个C++函数,根据处理返回不同类型的std::list
- 无法将 List 中的类型 'uint' 隐式转换为'T'(从类模板)
- list pushback一个包含字符串类型核心的结构
- (Qt或其他)拖放数据的mime类型的uri-list与协议http或ftp在Windows桌面或explorer.ex
- 抽象类和虚方法问题:不能将变量' list '声明为抽象类型' aStack
' aStack - 使用递归在List中查找int类型-何时返回
- 对指向std::list类型的共享指针赋值不起作用
- std::list类型可变变量的boost序列化不起作用