std::optional 是否在调用包含的对象函数时转发右值性?
Does std::optional forwards rvalueness when contained object functions are called?
C++ 鲜为人知的特性是 ref-qualifiers for member functions。
它在大多数情况下都像我预期的那样工作,但似乎 std::optional
没有将其即将消亡的知识转发给包含的对象成员函数。
例如考虑以下代码:
#include <chrono>
#include <iostream>
#include <optional>
struct Noisy {
Noisy(const std::string& data): data_(data){
}
~Noisy(){
std::cout << "Goodbye" << std::endl;
}
std::string data_;
const std::string& data() const & {
std::cout << "returning data by ref" << std::endl;
return data_;
}
std::string data() && {
std::cout << "returning data by move" << std::endl;
return std::move(data_);
}
};
int main() {
for (const auto chr: Noisy{"Heeeeeeeeeeeeeeeeello wooooorld"}.data()){
std::cout << chr;
}
std::cout << std::endl;
for (const auto chr: std::optional<Noisy>{"Heeeeeeeeeeeeeeeeello wooooorld"}->data()){
std::cout << chr;
}
std::cout << std::endl;
}
输出为:
returning data by move
Goodbye
Heeeeeeeeeeeeeeeeello wooooorld
returning data by ref
Goodbye
(crash in clang with sanitizer or garbage(UB))
我希望临时 std::optional
能够调用正确的 (data() &&
) 函数,但它似乎没有发生。
这是语言限制,还是 std::optional
没有正确的机制?
完整 godbolt link.
注意:我的动机是四处寻找,看看我是否可以聪明地在基于范围的 for 循环中更安全地使用我的 类,但实际上不值得付出努力,这个问题主要是关于学习语言。
重载运算符箭头不能做你想做的;它总是以指针结束。
当且仅当 x
是一个指针时,x->y
被标准定义为 (*x).y
;否则就是 (x.operator->())->y
。此递归仅在您点击指针时终止。1
并且没有指向临时类型的指针。试试这个:
const auto chr: (*std::optional<Noisy>{"Heeeeeeeeeeeeeeeeello wooooorld"}).data()
Which does call the rvalue method。 (通过@largest_prime)。
1这个递归也可以做到Turing complete computation.
C++ 鲜为人知的特性是 ref-qualifiers for member functions。
它在大多数情况下都像我预期的那样工作,但似乎 std::optional
没有将其即将消亡的知识转发给包含的对象成员函数。
例如考虑以下代码:
#include <chrono>
#include <iostream>
#include <optional>
struct Noisy {
Noisy(const std::string& data): data_(data){
}
~Noisy(){
std::cout << "Goodbye" << std::endl;
}
std::string data_;
const std::string& data() const & {
std::cout << "returning data by ref" << std::endl;
return data_;
}
std::string data() && {
std::cout << "returning data by move" << std::endl;
return std::move(data_);
}
};
int main() {
for (const auto chr: Noisy{"Heeeeeeeeeeeeeeeeello wooooorld"}.data()){
std::cout << chr;
}
std::cout << std::endl;
for (const auto chr: std::optional<Noisy>{"Heeeeeeeeeeeeeeeeello wooooorld"}->data()){
std::cout << chr;
}
std::cout << std::endl;
}
输出为:
returning data by move
Goodbye
Heeeeeeeeeeeeeeeeello wooooorld
returning data by ref
Goodbye
(crash in clang with sanitizer or garbage(UB))
我希望临时 std::optional
能够调用正确的 (data() &&
) 函数,但它似乎没有发生。
这是语言限制,还是 std::optional
没有正确的机制?
完整 godbolt link.
注意:我的动机是四处寻找,看看我是否可以聪明地在基于范围的 for 循环中更安全地使用我的 类,但实际上不值得付出努力,这个问题主要是关于学习语言。
重载运算符箭头不能做你想做的;它总是以指针结束。
当且仅当x
是一个指针时,x->y
被标准定义为 (*x).y
;否则就是 (x.operator->())->y
。此递归仅在您点击指针时终止。1
并且没有指向临时类型的指针。试试这个:
const auto chr: (*std::optional<Noisy>{"Heeeeeeeeeeeeeeeeello wooooorld"}).data()
Which does call the rvalue method。 (通过@largest_prime)。
1这个递归也可以做到Turing complete computation.