我很惊讶地得知移动构造函数(以及该事项的赋值)std::optional没有重置可选的移动,如[19.6.3.1/7]中所示,其中"bool(rhs)不变".
这也可以通过以下代码看出:
#include <ios>
#include <iostream>
#include <optional>
#include <utility>
int main() {
std::optional<int> foo{ 0 };
std::optional<int> bar{ std::move(foo) };
std::cout << std::boolalpha
<< foo.has_value() << '\n' // true
<< bar.has_value() << '\n'; // true
}
Run Code Online (Sandbox Code Playgroud)
这似乎与在标准库中移动的其他实例相矛盾,例如移动std::vector容器的位置通常以某种方式重置(在向量的情况下保证之后为空)以使其"无效",即使其中包含的对象也是如此他们自己已经离开了.这个或潜在的用例是否有任何理由支持,例如可能试图模仿相同类型的非可选版本的行为?
在使用线程一段时间后,我遇到了一种情况,我需要一个线程永远运行,直到调用一个函数(或任何类型的事件).为此,我创建了一个bool值来控制线程执行的函数内部的while循环,但我很快注意到在线程开始运行后外部变量没有更新,导致线程在被要求时永远不会停止.
下面是一些代表问题的简单代码:
#include <cstdio>
#include <thread>
#include <chrono>
class A {
public:
A();
void startThread();
void endThread();
private:
void threadCall();
bool active;
};
int main() {
A threadThing;
threadThing.startThread();
printf("[M] Thread Created\n");
std::this_thread::sleep_for(std::chrono::seconds(5));
threadThing.endThread();
printf("[M] Thread Killed\n");
std::this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}
A::A() {
active = false;
}
void A::startThread() {
active = true;
std::thread AThread(&A::threadCall, *this);
AThread.detach();
}
void A::endThread() {
active = false;
}
void A::threadCall() {
printf("[T] Thread Started\n");
while (active) {
std::this_thread::sleep_for(std::chrono::seconds(2));
}
printf("[T] Thread Ended\n");
} …Run Code Online (Sandbox Code Playgroud) 我遇到的问题似乎是非常简单的代码,但它完全符合我的期望:
码:
char b[sizeof(float)];
float a = 1.5f;
memcpy(b, &a, sizeof(float));
printf("%f\n", b[0]);
Run Code Online (Sandbox Code Playgroud)
输出:
62827075002794546937726511559700164562271693617156259118887055013962964939146547
22493354730179062365918845182857228200743453702107162763566167344423902681816648
14169764096333089859051972349071751428406066879715295195780847944297207011246001
33742258486014791122944.000000
Run Code Online (Sandbox Code Playgroud)
然而,当我这样做时它起作用:
char b[sizeof(int)];
int a = 3;
memcpy(b, &a, sizeof(int));
printf("%i\n", b[0]);
Run Code Online (Sandbox Code Playgroud)
输出:
3
Run Code Online (Sandbox Code Playgroud)
为什么会这样?是因为字节序还是其他什么?
最近,我尝试检测特定私有构造函数的存在,并遇到了std::is_constructible仅检查即时上下文而无法识别任何此类构造函数的问题。经过一些研究,我确实看到这里的一个答案提到,正确的方法是与有问题的班级交朋友,std::is_constructible以使其可以访问。
为了测试此方法是否有效,我尝试了以下测试代码
#include <type_traits>
class A {
private:
template<typename, typename ...>
friend struct std::is_constructible;
A() = default;
};
int main() {
static_assert(std::is_constructible<A>::value);
static_assert(std::is_constructible_v<A>);
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,此方法std::is_constructible在Visual Studio 2017中似乎可以使用,尽管随后我开始遇到的问题std::is_constructible_v。在他们的实现中,std::is_constructible他们没有在实际的结构本身上使用别名模板,而是直接调用内部使用的内在函数,而内在函数又忽略了好友声明。
认为这是其标准库实现中的一个错误,然后我在其他编译器中进行了测试,发现无论是clang还是gcc在任何情况下都不能传递此断言,这使我想知道它是否应该像这样完全起作用(链接文章上的某些评论似乎暗示这是一个错误,而其他人则表示不应考虑朋友声明)。
因此,主要的问题是该代码是否应该正常工作(因为它应该能够访问私有构造函数并传递断言),并且该方法将标准定义的访问限制为立即上下文?这里也提出了类似的问题,我不确定的主要事情是这种情况下“即时上下文”所意图的确切定义,因为这与链接问题中的示例稍有不同。
N4713 23.15.4.3.8 [meta.unary.prop] / 8的相关段落:
就像在与T和任何Arg不相关的上下文中一样,执行访问检查。仅考虑变量初始化的即时上下文的有效性。