jjzjj

c++ - boost optional 和 std::experimental optional assignment 之间的区别

coder 2023-11-15 原文

通常当函数返回 boost::optional 时我见过很多人返回空括号 {}指定一个空值,它工作正常并且比返回 boost::none 短.

我尝试做一些类似于清空 boost::optional<int> 的事情,但是当调用复制赋值运算符(或者很可能是移动赋值运算符)并在右侧使用空大括号时,空大括号被转换为 int 然后将该值分配给可选值,所以我最终得到变量设置为 0 而不是我预期的空值。这是一个例子 https://godbolt.org/g/HiF92v , 如果我用 std::experimental::optional 做同样的尝试我得到了我期望的结果(只需在示例中替换为 std::experimental::optional,您将看到指令变为 mov eax, eax)。

此外,如果我尝试为 boost 可选(非整数类型)使用不同的模板参数,一些编译器会编译(具有我期望的行为,这里是一个示例 http://cpp.sh/5j7n ),而其他编译器则不会。因此,即使对于相同的库,行为也会根据模板参数而有所不同。

我想了解这里发生了什么,我知道这与我在库中使用 C++14 功能这一事实有关,但在设计中并未考虑到这一点。我读了boost/optional header 但我迷失在细节中,我也尝试研究编译后的代码而不内联得到类似的结果。

我正在使用带有 -std=c++14 和 boost 1.57 的 gcc 4.9.2。

顺便说一句:我知道我应该使用 boost::optional::resetboost::none ,但我试图与代码库其余部分的语义保持一致。

最佳答案

要了解发生了什么,请先考虑这个例子:

void fun(int) { puts("f int"); }
void fun(double) { puts("f double"); }

int main() {
  fun({}); // error
}

这会导致编译器错误,因为重载解析是不确定的:doubleint同样适合。但是,如果非标量类型起作用,情况就不同了:

struct Wrap{};
void fun(int) { puts("f(int)"); }
void fun(Wrap) { puts("f(Wrap)"); }

int main() {
  fun({}); // ok: f(int) selected
}

这是因为标量更匹配。如果出于某种原因,我想要相同的两个重载,但同时我想要 fun({})选择过载 fun(Wrap) ,我可以稍微调整一下定义:

template <typename T>
std::enable_if_t<std::is_same<int, std::decay_t<T>>::value>
fun(T) { puts("f int"); }

void fun(Wrap) { puts("f(Wrap)"); }

fun(Wrap)保持不变,但第一个重载现在是一个模板,它接受任何 T .但是用enable_if我们对其进行约束,使其仅适用于类型 int .所以,这是一个相当“人工”的​​模板,但它确实完成了工作。如果我打电话:

fun(0); // picks fun(T)

人工模板被选中。但是如果我输入:

fun({}); // picks fun(Wrap)

人工模板仍然是模板,因此在这种情况下从不考虑类型推导,唯一可见的重载是fun(Wrap) , 所以它被选中。

std::optional<T> 中使用了相同的技巧: 它没有来自 T 的分配.相反,它有一个类似的人工分配模板,它接受任何 U , 但后来受到约束,因此 T == U .您可以在引用实现中看到它 here .

boost::optional<T>已经在 C++11 之前实现,不知道这个“重置习语”。因此它有一个来自 T 的正常分配。 ,并且在 T 的情况下恰好是来自 T 的这个赋值的标量是首选。因此存在差异。

考虑到所有这些,我认为 Boost.Optional 有一个错误,它做的事情与 std::optional 相反.即使它不能在 Boost.Optional 中实现,它至少应该编译失败,以避免运行时意外。

关于c++ - boost optional 和 std::experimental optional assignment 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40391244/

有关c++ - boost optional 和 std::experimental optional assignment 之间的区别的更多相关文章

  1. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  2. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  3. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  4. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  5. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  6. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  7. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  8. [工业相机] 分辨率、精度和公差之间的关系 - 2

    📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年

  9. spring.profiles.active和spring.profiles.include的使用及区别说明 - 2

    转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev

  10. ruby - 这两段代码有什么区别? - 2

    打印1:defsum(i)i=i+[2]end$x=[1]sum($x)print$x打印12:defsum(i)i.push(2)end$x=[1]sum($x)print$x后者是修改全局变量$x。为什么它在第二个例子中被修改而不是在第一个例子中?类Array的任何方法(不仅是push)都会发生这种情况吗? 最佳答案 变量范围在这里无关紧要。在第一段代码中,您仅使用赋值运算符=为变量i赋值,而在第二段代码中,您正在修改$x(也称为i)使用破坏性方法push。赋值从不修改任何对象。它只是提供一个名称来引用一个对象。方法要么是破坏性

随机推荐