当前位置:  开发笔记 > 编程语言 > 正文

C++临时应该是不变的吗?

如何解决《C++临时应该是不变的吗?》经验,为你挑选了1个好方法。

我有一个C++类,它具有以下接口:

class F {
public:
    F(int n, int d);
    // no other constructors/assignment constructors defined
    F& operator *= (const F&);
    F& operator *= (int);
    int n() const;
    int d() const;
};

我有以下代码:

const F a{3, 7};
const F b{5, 10};
auto result = F{a} *= b; // How does this compile?

在Visual Studio(VS)2013下,注释行编译时没有错误.在VS2015下,产生错误C2678:

error C2678: binary '*=': no operator found 
    which takes a left-hand operand of type 'const F' 
    (or there is no acceptable conversion)
note: could be 'F &F::operator *=(const F &)'
note: or       'F &F::operator *=(int)'
note: while trying to match the argument list '(const F, const F)'

我的期望是F{a}创建一个非const临时副本,a然后operator *= (b)将临时对象分配给该临时副本result.我没想到临时是一个常数.有趣的是:auto result = F(a) *= b;在VS2015中编译没有错误,我认为应该在语义上相同.

我的问题是:VS2015或VS2013的行为是正确的?为什么?

非常感谢



1> Shafik Yaghm..:

Visual Studio 2015未生成正确的结果:

F{a}

结果应该是一个prvalue(gcc和clang都有这个结果),但它产生一个左值.我使用OP的代码的以下修改版本来产生这个结果:

#include 

class F {
public:
    F(int n, int d) :n_(n), d_(d) {};
    F(const F&) = default ;
    F& operator *= (const F&){return *this; }
    F& operator *= (int) { return *this; }
    int n() const { return n_ ; }
    int d() const { return d_ ; }
    int n_, d_ ;
};

template
struct value_category {
    static constexpr auto value = "prvalue";
};

template
struct value_category {
    static constexpr auto value = "lvalue";
};

template
struct value_category {
    static constexpr auto value = "xvalue";
};

#define VALUE_CATEGORY(expr) value_category::value

int main()
{
  const F a{3, 7};
  const F b{5, 10};   
  std::cout << "\n" <<  VALUE_CATEGORY( F{a} ) <<  "\n";
}

给Luc Danton提示VALUE_CATEGORY()代码.

使用webcompiler的 Visual Studio 具有相对较新的版本,可生成:

lvalue

在这种情况下必须是const才能产生我们看到的错误.虽然gcc和clang(看到它直播)产生:

prvalue

这可能与同样令人困惑的Visual Studio bug std :: move of string literal有关 - 哪个编译器是正确的?.

注意我们可以使用const F得到与gcc和clang相同的问题:

using cF = const F ;
auto result = cF{a} *= b; 

因此,Visual Studio不仅为我们提供了错误的值类别,而且还随意添加了一个cv-qualifier.

正如汉斯在他对你的问题的评论中指出的那样F(a)产生了预期的结果,因为它正确地产生了一个prvalue.

C++标准草案的相关部分是5.2.3 [expr.type.conv]部分,其中说:

类似地,一个simple-type-specifier或typename-specifier后跟一个braced-init-list,用指定的braced-init-list创建一个指定类型direct-list-initialized(8.5.4)的临时对象及其值是临时对象作为prvalue.

请注意,据我所知,这不是"旧的MSVC左值投射错误".该问题的解决方案是使用/Zc:rvalueCast哪个不能解决此问题.这个问题在不正确添加cv-qualifier方面也有所不同,据我所知,这与前一个问题没有关系.

推荐阅读
勤奋的瞌睡猪_715
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有