无用的知识又增加了: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.mzph.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; 如果所读的字符是…