[英]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}
轉換為std::initializer_list<long>
類似於上面的示例{"onm", "two", "three"}
,因此您將獲得一個包含單個元素的向量,該向量具有值3。
第二行是不同的。 它構造了一個由3個空字符串組成的向量。 為什么? 因為初始化列表 {3}
絕不能轉換為std::initializer_list<string>
,所以“普通”構造函數std::vector<T>::vector(size_t, T = T())
插入並給出三個默認構造的字符串。
好吧,這應該與第二個大致相同,對吧? 它應該給出一個空向量,換句話說,帶有零個默認構造的字符串。 錯誤! 。 0
可以視為空指針常量,並驗證std::initializer_list<string>
。 只有這次,該列表中的單個字符串才由nullpointer構造,這是不允許的,因此會出現異常。
沒有類型推斷,因為向量僅提供帶有初始化程序列表的完全專用的構造函數。 我們可以添加一個模板間接播放來與類型演繹一起玩。 下面的示例顯示std::initializer_list<const char*>
是向量構造函數的無效參數。
#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" } );
}
從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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.