簡體   English   中英

為什么縮小轉換不會阻止不正確類型的map.insert()失敗?

[英]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.

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