無用的知識又增加了:is_assignable means?

?std::pair的默認operator=被delete掉了,取而代之的是兩個enable_if版本。

為什么這么設計,我的理解是在std::map里,已經保存的元素的key值是不能被修改的,比如

注意,下面的代碼會修改key值,編譯時出現錯誤:
兩個enable_if版本推導失敗,最后落到了:pair& operator=(const volatile pair&) = delete;
這個版本,但這個版本又被刪除了。所以出現了編譯錯誤。{std::map<int, int> m;//初始化auto it = m.begin();*it = std::make_pair(1, 1); //問題就出在這里
}就會提示:
error C2679: 二進制“=”: 沒有找到接受“std::pair<int,int>”類型的右操作數的運算符(或沒有可接受的轉換)
1>d:\devtools\vs2017\vc\tools\msvc\14.16.27023\include\utility(276): note: 可能是“std::pair<const _Kty,_Ty> &std::pair<const _Kty,_Ty>::operator =(volatile const std::pair<const _Kty,_Ty> &)”
1>        with
1>        [
1>            _Kty=int,
1>            _Ty=int
1>        ]
1>c:\work\hchx\ceripipe\codestudy\consoleapplication2\consoleapplication1\consoleapplication1.cpp(2114): note: 嘗試匹配參數列表“(std::pair<const _Kty,_Ty>, std::pair<int,int>)”時
1>        with
1>        [
1>            _Kty=int,
1>            _Ty=int
1>        ]

代碼:
std::pair<int, int> data0 = std::make_pair(1, 2);
std::pair<const int, int> data1 = std::make_pair(3, 4);
data0 = data1;堆棧中可以看到推導結果:
1.exe!std::pair<int,int>::operator=<int const ,int,0>
(const std::pair<int const ,int> & _Right={...}) 行 288	C++推導出的符號,
_Ty1和_Other1類型是:const int
_Ty2和_Other2類型是:int查看pair的operator=的enable_if不分,
is_assignable<_Ty1&, const _Other1&>怎么算,替換下來就是:
is_assignable<const int&, const const int&>
看到const const int&,居然有兩個const,能行嗎?考慮到is_asignable的實現,也就是相當于,
{using T = decltype(declval<int&>() = declval<const const int&>());int b = 0;T a = b;std::ignore = a;
}
vs2015下編譯成功。神奇。
而is_assignable<_Ty1&, const _Other1&>就是:is_assignable<int&, const int&>
{using T = decltype(declval<int&>() = declval<const int&>());int b = 0;T a = b;std::ignore = a;
}
vs2015下也能編譯成功。std::cout << boost::typeindex::type_id_with_cvr<const const int&>().pretty_name() << std::endl;
打印結果是:int const & __ptr64所以,enable_if_t<conjunction_v<is_assignable<_Ty1&, const _Other1&>,is_assignable<_Ty2&, const _Other2&>>, int>推導成功,
相當于:enable_if_t<conjunction_v<true,true>, int> 
-> enable_if_t<true, int> 
-> int所以才走到了下面的operator=的版本。結合源碼:pair& operator=(const volatile pair&) = delete; //默認的版本已被刪除template<class _Other1 = _Ty1, //_Ty1:const int, _Other1: const intclass _Other2 = _Ty2, //_Ty2:int      , _Other2: intenable_if_t<conjunction_v<is_assignable<const int&, const const int&>,is_assignable<int&      , const int&>>, int> = 0>pair& operator=(const pair<const int, int>& _Right)_NOEXCEPT_COND(is_nothrow_assignable_v<_Ty1&, const _Other1&>&& is_nothrow_assignable_v<_Ty2&, const _Other2&>)	// strengthened{first = _Right.first;second = _Right.second;return (*this);}

How to interpret declval<_Dest>() = declval<_Src>() in is_assignable

I am trying to figure out how to interpret declval<_Dest>() = declval<_Src>() in the implementation of is_assignable.

declval turns a type into a reference. Given that, I translate the expression into one of the following four possibilities:

  1. _Dest&& = _Src&&
  2. _Dest&& = _Src&
  3. _Dest& = _Src&&
  4. _Dest& = _Src&

I then created two helper functions.

template <typename T> T rvalue();
template <typename T> T& lvalue();

My understanding is the four expressions can be realized by using the template functions.

  1. _Dest&& = _Src&& -----> rvalue<_Dest>() = rvalue<_Src>()

Same goes for the other three.

Then I simulated decltype(declval<_Dest>() = declval<_Src>(), ..) by compiling the templated function version of each of the possibilities for three pairs of concrete types.

  • _Dest=int, _Src=int. Compiler accepts #3 and #4. is_assignable returned true for #3 and #4. They agreed.
  • _Dest=int, _Src=double. Same result as
  • _Dest=double, _Src=int. For this one, the compiler and is_assignable didn't agree. Compiler again does not like assigning to rvalues. However, is_assignable returns true for all four possibilities.

My questions are

  • Did I interpret declval<_Dest>() = declval<_Src>() correctly? In order words, does this really translate into the four possibilities. If yes, can each one be mapped to a templated function expression?
  • Why the compiler and is_assignable disagree on the _Dest=double, _Src=int case?

Thanks.

  • c++
  • c++11

Share

Improve this question

Follow

edited Dec 6, 2013 at 5:34

ildjarn

63k99 gold badges131131 silver badges216216 bronze badges

asked Dec 6, 2013 at 2:35

Candy Chiu

6,67999 gold badges5151 silver badges7070 bronze badges

  • 1

    Which compiler is "the" compiler? At least one compiler appears to work precisely as you expect.

    –?Igor Tandetnik

    ?Commented Dec 6, 2013 at 3:18?
  • The compiler is VC++2013

    –?Candy Chiu

    ?Commented Dec 6, 2013 at 13:21?
https://ideone.com/QdRjZB#include <iostream>
#include <type_traits>
using namespace std;template <typename T>
T rvalue() { return T(); }template <typename T>
T& lvalue() { static T t; return t; }int main() {cout << is_assignable<double, int>::value;cout << is_assignable<double, int&>::value;cout << is_assignable<double&, int>::value;cout << is_assignable<double&, int&>::value;// rvalue<double>() = rvalue<int>(); // Doesn't compile// rvalue<double>() = lvalue<int>(); // Doesn't compilelvalue<double>() = rvalue<int>(); // OKlvalue<double>() = lvalue<int>(); // OKreturn 0;
}

一個回答:

std::declval is actually specified to be (C++11 §20.2.4 [declval] p1):

template <class T>
typename add_rvalue_reference<T>::type declval() noexcept;

The result of the reference collapsing rules (§8.3.2 [dcl.ref] p6) is that declval returns an lvalue reference when T is an lvalue reference type, and an rvalue reference otherwise. So yes, your interpretation is correct.

If your compiler thinks that double&& is assignable from any type, then it has a bug. §5.17 [expr.ass] p1 states:

The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue referring to the left operand.

[emphasis mine].

Many programmers choose to emulate this behavior - assingment only to lvalues - with their own types by declaring the assignment operators with an lvalue reference qualifier:

class foo {foo& operator = (const foo&) & = default;foo& operator = (foo&&) & = default;
};

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/67243.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/67243.shtml
英文地址,請注明出處:http://en.pswp.cn/web/67243.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

能量提升法三:贊美

前情回顧&#xff1a; 《能量提升法二&#xff1a;感恩》 片段&#xff1a;“感恩&#xff0c;就像是在跟世界說&#xff1a;謝謝你&#xff0c;我收到了&#xff0c;我很喜歡&#xff0c;請多來點” 把它歸還人海&#xff0c;就當作每一個人&#xff0c;都有可能是曾經幫助…

25美賽ABCDEF題詳細建模過程+可視化圖表+參考論文+寫作模版+數據預處理

詳情見該鏈接&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 25美國大學生數學建模如何準備&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;-CSDN博客文章瀏覽閱讀791次&#xff0c;點贊13次&#xff0c;收藏7次。通過了解比賽基本…

2025企業繁體鏡像站鏡像站群版 | 干擾碼+拼音插入

技術背景 高效的SEO優化和內容采集是企業站群系統的核心競爭力。本文將詳細介紹一套企業級網站鏡像工具包&#xff0c;重點展示其在SEO優化、內容采集、智能處理等方面的創新實現。 系統特性 1. SEO優化功能 關鍵詞智能布局標題標簽優化鏈接結構優化移動端適配頁面加速優化…

動態規劃<九>兩個數組的dp

目錄 引例 LeetCode經典OJ題 1.第一題 2.第二題 3.第三題 4.第四題 5.第五題 6.第六題 7.第七題 引例 OJ傳送門LeetCode<1143>最長公共子序列 畫圖分析&#xff1a; 使用動態規劃解決 1.狀態表示 ------經驗題目要求 經驗為選取第一個字符串的[0,i]區間以及第二個字…

大數據學習之SCALA分布式語言三

7.集合類 111.可變set一 112.可變set二 113.不可變MAP集合一 114.不可變MAP集合二 115.不可變MAP集合三 116.可變map一 package com . itbaizhan . chapter07 //TODO 2. 使用 mutable.Map 前導入如下包 import scala . collection . mutable // 可變 Map 集合 object Ma…

MongoDB中常用的幾種高可用技術方案及優缺點

MongoDB 的高可用性方案主要依賴于其內置的 副本集 (Replica Set) 和 Sharding 機制。下面是一些常見的高可用性技術方案&#xff1a; 1. 副本集 (Replica Set) 副本集是 MongoDB 提供的主要高可用性解決方案&#xff0c;確保數據在多個節點之間的冗余存儲和自動故障恢復。副…

基于OSAL的嵌入式裸機事件驅動框架——整體架構調度機制

參考B站up主【架構分析】嵌入式祼機事件驅動框架 感謝大佬分享 任務ID &#xff1a; TASK_XXX TASK_XXX 在系統中每個任務的ID是唯一的&#xff0c;范圍是 0 to 0xFFFE&#xff0c;0xFFFF保留為SYS_TSK_INIT。 同時任務ID的大小也充當任務調度的優先級&#xff0c;ID越大&#…

WGCLOUD運維工具從入門到精通 - 如何設置主題背景

需要升級到WGCLOUD的v3.5.7或者以上版本&#xff0c;才會支持自定義設置主題背景色 WGCLOUD下載&#xff1a;www.wgstart.com 我們登錄后&#xff0c;在右上角點擊如下的小圖標&#xff0c;就可以設置主題背景色了&#xff0c;包括&#xff1a;經典白&#xff08;默認&#x…

LigerUI在MVC模式下的響應原則

LigerUI是基于jQuery的UI框架&#xff0c;故他也是遵守jQuery的開發模式&#xff0c;但是也具有其特色的偵聽函數&#xff0c;那么當LigerUI作為View層的時候&#xff0c;他所發送后端的必然是表單的數據&#xff0c;在此我們以倆個div為例&#xff1a; {Layout "~/View…

基于RIP的MGRE VPN綜合實驗

實驗拓撲 實驗需求 1、R5為ISP&#xff0c;只能進行IP地址配置&#xff0c;其所有地址均配為公有IP地址&#xff1b; 2、R1和R5間使用PPP的PAP認證&#xff0c;R5為主認證方&#xff1b; R2與R5之間使用ppp的CHAP認證&#xff0c;R5為主認證方&#xff1b; R3與R5之間使用HDLC封…

git的理解與使用

本地的git git除了最經典的add commit push用來做版本管理&#xff0c;其實他的分支管理也非常強大 可以說你學好了分支管理&#xff0c;就可以完成團隊的配合協作了 git倉庫 我們可以使用git init來初始化一個git倉庫&#xff0c;只要能看見.git文件夾&#xff0c;就代表這…

Java 編程初體驗

Java學習資料 Java學習資料 Java學習資料 一、引言 在當今數字化的時代&#xff0c;編程已然成為一項極具價值的技能。而 Java 作為一門廣泛應用于企業級開發、移動應用、大數據等眾多領域的編程語言&#xff0c;吸引著無數初學者投身其中。當我們初次踏入 Java 編程的世界&…

STM32 對射式紅外傳感器配置

這次用的是STM32F103的開發板&#xff08;這里面的exti.c文件沒有how to use this driver 配置說明&#xff09; 對射式紅外傳感器 由一個紅外發光二極管和NPN光電三極管組成&#xff0c;M3固定安裝孔&#xff0c;有輸出狀態指示燈&#xff0c;輸出高電平燈滅&#xff0c;輸出…

https數字簽名手動驗簽

以bing.com 為例 1. CA 層級的基本概念 CA 層級是一種樹狀結構&#xff0c;由多個層級的 CA 組成。每個 CA 負責為其下一層級的實體&#xff08;如子 CA 或終端實體&#xff09;頒發證書。層級結構的頂端是 根 CA&#xff08;Root CA&#xff09;&#xff0c;它是整個 PKI 體…

【自然語言處理(NLP)】深度循環神經網絡(Deep Recurrent Neural Network,DRNN)原理和實現

文章目錄 介紹深度循環神經網絡&#xff08;DRNN&#xff09;原理和實現結構特點工作原理符號含義公式含義 應用領域優勢與挑戰DRNN 代碼實現 個人主頁&#xff1a;道友老李 歡迎加入社區&#xff1a;道友老李的學習社區 介紹 **自然語言處理&#xff08;Natural Language Pr…

Niagara學習筆記

橙色 發射器 , 綠色 粒子, 紅色 渲染器 Emitter State 發射器狀態 Life Cycle Mode&#xff08;生命周期模式&#xff09; 選擇Self就是發射器自身管理生命周期 Loop Behavior 決定粒子發射次數 一次&#xff08;Once&#xff09;&#xff1a;發射器只播放一次多次&#…

17 一個高并發的系統架構如何設計

高并發系統的理解 第一:我們設計高并發系統的前提是該系統要高可用&#xff0c;起碼整體上的高可用。 第二:高并發系統需要面對很大的流量沖擊&#xff0c;包括瞬時的流量和黑客攻擊等 第三:高并發系統常見的需要考慮的問題&#xff0c;如內存不足的問題&#xff0c;服務抖動的…

2025數學建模美賽|F題成品論文

國家安全政策與網絡安全 摘要 隨著互聯網技術的迅猛發展&#xff0c;網絡犯罪問題已成為全球網絡安全中的重要研究課題&#xff0c;且網絡犯罪的形式和影響日益復雜和嚴重。本文針對網絡犯罪中的問題&#xff0c;基于多元回歸分析和差異中的差異&#xff08;DiD&#xff09;思…

適配Android16

Android16新特性 Android 16帶來了許多新特性和改進&#xff0c;提升了系統的流暢度、用戶體驗和安全性。對于應用開發者來說&#xff0c;適配Android 16可以確保應用在該版本上的兼容性和性能&#xff0c;同時也可以利用其新特性為用戶提供更好的服務。以下是Android 16的一些…

【C++數論】880. 索引處的解碼字符串|2010

本文涉及知識點 數論&#xff1a;質數、最大公約數、菲蜀定理 LeetCode880. 索引處的解碼字符串 給定一個編碼字符串 s 。請你找出 解碼字符串 并將其寫入磁帶。解碼時&#xff0c;從編碼字符串中 每次讀取一個字符 &#xff0c;并采取以下步驟&#xff1a; 如果所讀的字符是…