簡體   English   中英

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};

這些是做什么的?

  1. 第一行相對容易。 可以將初始化程序列表 {3}轉換為std::initializer_list<long>類似於上面的示例{"onm", "two", "three"} ,因此您將獲得一個包含單個元素的向量,該向量具有值3。

  2. 第二行是不同的。 它構造了一個由3個空字符串組成的向量。 為什么? 因為初始化列表 {3}絕不能轉換為std::initializer_list<string> ,所以“普通”構造函數std::vector<T>::vector(size_t, T = T())插入並給出三個默認構造的字符串。

  3. 好吧,這應該與第二個大致相同,對吧? 它應該給出一個空向量,換句話說,帶有零個默認構造的字符串。 錯誤! 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;
}

http://ideone.com/UJ4a0i

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM