(为什么)是std :: chrono文字左值?

时间:2020-08-28 11:14:31

标签: c++

基本上,该示例说明了一切:分配给std :: chrono文字-不给出错误消息。 我尝试了gcc,clang和vc(c ++ 17),所有这些编译器都接受了它。 这是预期的行为吗?

#include <chrono>
using namespace std::chrono_literals;

int main()
{
    10ms  += 1ms;       // would expect error here
    12ms = 10ms;        // and here
    // 3 = 4;           // like here
    return 0;
}

2 个答案:

答案 0 :(得分:25)

std :: chrono文字是左值吗?

不。 std::chrono_literals是prvalue。

这是预期的行为吗?

这是标准所规定的。

这些值属于类类型。只要该类是可分配的,并且可以为该类类型的右值分配 1 ,并且它们的赋值运算符重载不符合左值引用的条件。像所有成员函数一样,类的赋值运算符默认情况下不是lvalue ref限定的,并且几乎没有任何标准类具有这种限定的重载 2 -我不知道任何,但是如果有,{{ 1}}不是其中之一。

请注意,文字未修改。左操作数是一个临时对象,在这种情况下将被丢弃。


另一个简单的分配右值的示例:

std::chrono::duration

1 这实际上是一个有用的功能,尽管用例并不多。这是一个有用的示例:

std::string{"temporary"} = "this is pointless, but legal";

2 在C ++ 11之前,没有ref限定符,因此可以分配所有可分配类类型的右值。为了保持向后兼容性,不能更改默认值,也不能更改预先存在的类(至少在没有弃用期限的情况下)。 std::vector<bool> vec{true, false, true}; vec[1] = true; // vec[1] is an rvalue 是在C ++ 11中添加的,因此它本可以具有合格的赋值运算符,但是标准作者似乎更喜欢不限定其赋值运算符。

答案 1 :(得分:16)

std::chrono文字不是左值。它们可能看起来像这样,但是您看到的实际上是r值对赋值运算符的调用。为什么允许这样做?具体来说,因为成员分配运算符

constexpr duration& operator+=(const duration& d)
[time.duration.arithmetic]/9指定的

不使用任何ref限定词,这表示不拒绝被r值调用

与下面的示例比较(在上面的duration中实现)

struct Foo {
    unsigned long long i;
    constexpr Foo& operator+=(const Foo& d) { return *this; }
};

constexpr Foo operator"" _Foo (unsigned long long i) {
    return Foo{i};
}

int main() {
    1_Foo += 2_Foo;  // OK!
}
与以下示例相比,

显式地使用& ref限定符隐式禁止调用r值:

struct Foo {
    unsigned long long i;
    constexpr Foo& operator+=(const Foo& d) & { return *this; }
};

constexpr Foo operator"" _Foo (unsigned long long i) {
    return Foo{i};
}

int main() {
    1_Foo += 2_Foo;  // error: no viable overloaded '+='
}

,或者下面的示例,明确删除了r值重载:

struct Foo {
    unsigned long long i;
    constexpr Foo& operator+=(const Foo& d) & { return *this; }
    constexpr Foo& operator+=(const Foo& d) && = delete;
};

constexpr Foo operator"" _Foo (unsigned long long i) {
    return Foo{i};
}

int main() {
    1_Foo += 2_Foo;  // error: overload resolution selected deleted operator '+='
}

有关r值限定符的详细信息以及如何使用它们以禁止分配r-value,请参见例如以下问答: