[英]Why is narrowing conversion not preventing this map.insert() of an incorrect type from failing?
將std::pair<uint64_t, uint64_t>
插入到C ++ std::map<uint64_t, int>
,編譯器和程序都不會抱怨,即使數據類型uint64_t
無法傳遞值也是如此。
換句話說, std::pair<uint64_t, uint64_t>(2, -2)
的縮小轉換不起作用,並且默認為地圖的類型std::map<uint64_t, int>
當我使用g++ -Wall -Wconversion -Wextra -pedantic test/test_wrong_insert.cpp && ./a.out
編譯並執行以下代碼時:
#include<map>
#include<iostream>
void print_map(std::map<uint64_t, int> & m){
std::cout << "The map is now: {";
for (const auto & n: m){
std::cout << '(' << n.first << ',' << n.second << ") ";
}
std::cout << "}\n";
}
int main(){
std::map<uint64_t, int> m;
auto ret = m.insert(std::pair<uint64_t, uint64_t>(2,-2));
std::cout << "Tried to insert std::pair<uint64_t, uint64_t>(2,-2). ";
std::cout << "Return: " << ret.second << '\n';
print_map(m);
}
......這是輸出:
Tried to insert std::pair<uint64_t, uint64_t>(2,-2). Return: 1
The map is now: {(2,-2) }
為什么std::pair<uint64_t,uint64_t> x{-1,-2}
不會產生錯誤,如何使其導致錯誤?
為什么
std::pair<uint64_t,uint64_t> x{-1,-2}
不會產生錯誤?
這是由參與重載解析的構造函數模板引起的,當兩個參數都可以用於構造uint64_t
對象(或者您實例化std::pair
with的任何類型)。 它是std::pair
構造函數列表中的重載(3),其模板參數推導導致轉換為有意轉換(如auto n = uint64_t{-42};
或static_cast<uint64_t>(-42);
) - 因此沒有警告。 您無法做到這一點,因為無法明確給出構造函數模板的模板參數,如此處所述 。
[...]如何使它導致錯誤?
使用std::make_pair
並且不依賴於模板參數推導:
auto p = std::make_pair<uint64_t, uint64_t>(-42, -42);
// Be explicit: ^^^^^^^^ ^^^^^^^^
當您使用-Wsign-conversion
編譯上述代碼段時(重要: -Wconversion
不會-Wconversion
它!),它會給您一個警告(顯然,添加-Werror
將其視為錯誤)。
這個問題std::map::insert
是一樣的,(2)見超載這里 。 這將任何可用的給定參數轉換為value_type
對象,並將其視為任何轉換將是調用者的意圖。 有趣的是, std::set
上的等效成員函數更受限制。 所以這被抓住了:
std::set<uint64_t> s;
s.insert(-42); // complains with -Wsign-conversion
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.