如果我写这个
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")};
避免与所涉及模板的类型推断机制相关的问题?我会保持同样的优化?
匿名用户
从…起http://en.cppreference.com/w/cpp/language/string_literal:
非固定字符串文字的类型是常量字符[]
因此,事情是这样的:
#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::initializer_list
#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" } );
}
现场演示
更新:回答您关于类型推断的问题:向量的初始值设定项列表构造函数
尽管如此,这里应用的类型转换和重载解析规则还是有一些有趣的地方,因此我将保留我的初始答案,因为您已经接受了它:
原始答案:
起初,编译器只看到初始化程序列表{"one","二","三"}
,这只是初始化程序的列表,还不是std::类型的对象initializer_list
。
然后它试图找到向量的适当构造函数
因此,编译器决定创建std::initializer\u list的实际对象
另一个可能更有趣的例子:
std::vector<long> vl1{3};
std::vector<string> vs1{3};
std::vector<string> vs2{0};
这些是做什么的?
>
第一行比较简单,初始化列表
{3}
可以转换成std::initializer_list
第二行不同,它构造了一个3个空字符串的向量,为什么呢?因为初始化列表
{3}
绝不能转换成std::initializer_list
这个应该和第二个大致相同,对吧?它应该给出一个空向量,换句话说,没有默认构造的字符串。错误!。可以将0视为nullpointer常量,并验证std::initializer\u列表
主要内容:1 Java8 类型推断的介绍,2 Java8 类型推断的案例1,3 Java8 类型推断的案例21 Java8 类型推断的介绍 类型推断是Java的一项功能,它使编译器可以查看每个方法调用和相应的声明以确定参数的类型。 Java在Java 8中提供了类型推断的改进版本。 1.1 Java8以前 在下面的声明中,我们在一侧提到了arraylist的类型。这种方法是在Java 7中引入的。在这里,您可以将第二面留为<>,并且编译器将通过引用变量的类型来推断其类型。 1.2 Java8以后
TypeScript 类型检查机制包含三个部分: 类型推断 类型保护 类型兼容性 本节介绍其中的类型推断,类型推断主要用于那些没有明确指出类型的地方帮助确定和提供类型,这是 TypeScript 的一种能力。 类型推断是有方向的,要注意区分从左向右和从右向左两种推断的不同应用。 1. 慕课解释 类型推断的含义是不需要指定变量类型或函数的返回值类型,TypeScript 可以根据一些简单的规则推断其
01 模板类型推断机制 auto 推断的基础是模板类型推断机制,但部分特殊情况下,模板推断机制不适用于 auto 模板的形式可以看成如下伪代码 template<typename T> void f(ParamType x); // ParamType 即 x 的类型 调用可看成 f(expr); 编译期间,编译器用 expr 推断 T 和 ParamType,实际上两者通常不一致,比如 te
在以下代码中: 如何避免在对b的调用中为N指定2?为什么不能自动推断出这种类型?没有它,我得到了错误: 'b':找不到匹配的重载函数'int b(int, constd::array
为了方便,并不总是需要明确指定一个变量的类型,编译器会通过第一个向这个对象赋予的值的类型来进行推断1。 uint24 x = 0x123; var y = x; 函数的参数,包括返回参数,不可以使用var这种不指定类型的方式。 需要特别注意的是,由于类型推断是根据第一个变量进行的赋值。所以代码for (var i = 0; i < 2000; i++) {}将是一个无限循环,因为一个uint8的