我试图std::thread用一个不带参数和返回的成员函数构造一个void.我无法弄清楚任何有效的语法 - 编译器无论如何都会抱怨.实现的正确方法是什么,spawn()以便返回std::thread执行的test()?
#include <thread>
class blub {
void test() {
}
public:
std::thread spawn() {
return { test };
}
};
Run Code Online (Sandbox Code Playgroud) P0137引入了函数模板, std::launder并在有关联合,生命周期和指针的部分中对标准进行了许多更改.
这篇论文解决了什么问题?我必须注意哪些语言的变化?我们在做什么launder?
C++ 20概念的一个角落是,在某些情况下你必须编写requires requires.例如,[expr.prim.req]/3中的这个例子:
甲需要表达也可以在使用需要子句([温度])作为写在模板参数特设约束,如下面的一个的一种方法:
Run Code Online (Sandbox Code Playgroud)template<typename T> requires requires (T x) { x + x; } T add(T a, T b) { return a + b; }第一个需要引入requires子句,第二个需要引入requires-expression.
需要第二个requires关键字的技术原因是什么?为什么我们不能只允许写作:
template<typename T>
requires (T x) { x + x; }
T add(T a, T b) { return a + b; }
Run Code Online (Sandbox Code Playgroud)
(注意:请不要回答那个语法requires吧)
另请参见 C++标准列表和默认构造类型
不是一个主要问题,只是烦人,因为我不希望我的类在没有特定参数的情况下被实例化.
#include <map>
struct MyClass
{
MyClass(int t);
};
int main() {
std::map<int, MyClass> myMap;
myMap[14] = MyClass(42);
}
Run Code Online (Sandbox Code Playgroud)
这给了我以下g ++错误:
/usr/include/c++/4.3/bits/stl_map.h:419:错误:没有用于调用'MyClass()'的匹配函数
如果我添加一个默认构造函数,这编译很好; 我确信它不是由不正确的语法引起的.
假设我有一个类型,我想将其默认构造函数设为私有.我写了以下内容:
class C {
C() = default;
};
int main() {
C c; // error: C::C() is private within this context (g++)
// error: calling a private constructor of class 'C' (clang++)
// error C2248: 'C::C' cannot access private member declared in class 'C' (MSVC)
auto c2 = C(); // error: as above
}
Run Code Online (Sandbox Code Playgroud)
大.
但是,构造函数结果证明不像我想象的那样私密:
class C {
C() = default;
};
int main() {
C c{}; // OK on all compilers
auto c2 = C{}; // OK on …Run Code Online (Sandbox Code Playgroud) c++ default-constructor language-lawyer aggregate-initialization c++11
(参考这个问题和答案.)
在C++ 17标准之前,[basic.compound]/3中包含以下句子:
如果类型T的对象位于地址A,则类型为cv T*的指针(其值为地址A)被称为指向该对象,而不管该值是如何获得的.
但是自从C++ 17以来,这句话已被删除.
例如,我相信这句话使这个示例代码定义,并且从C++ 17开始这是未定义的行为:
alignas(int) unsigned char buffer[2*sizeof(int)];
auto p1=new(buffer) int{};
auto p2=new(p1+1) int{};
*(p1+1)=10;
Run Code Online (Sandbox Code Playgroud)
在C++ 17之前,p1+1保持地址*p2并具有正确的类型,因此*(p1+1)是指向*p2.在C++中,17 p1+1是一个指向前端的指针,所以它不是指向对象的指针,我相信它不是可以解除引用的.
对标准权的这种修改的解释是否还有其他规则来补偿所引用的句子的删除?
switch 语句可能非常有用,但会导致程序员忘记break语句的常见错误:
switch(val) {
case 0:
foo();
break;
case 1:
bar();
// oops
case 2:
baz();
break;
default:
roomba();
}
Run Code Online (Sandbox Code Playgroud)
你不会明显得到警告,因为有时明确需要通过.良好的编码风格建议在你的堕落是故意的时候发表评论,但有时这是不够的.
我很确定这个问题的答案是否定的,但是:如果你case不这样做,那么当前(或将来会提出)是否能够让编译器抛出错误(或者至少是警告!)至少有一种break;或某种效果// fallthru?使用switch语句有一个防御性编程选项会很好.
假设我正在编写一个函数来打印字符串的长度:
template <size_t N>
void foo(const char (&s)[N]) {
std::cout << "array, size=" << N-1 << std::endl;
}
foo("hello") // prints array, size=5
Run Code Online (Sandbox Code Playgroud)
现在我想扩展foo以支持非数组:
void foo(const char* s) {
std::cout << "raw, size=" << strlen(s) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
但事实证明,这破坏了我原来的预期用途:
foo("hello") // now prints raw, size=5
Run Code Online (Sandbox Code Playgroud)
为什么?这不需要数组到指针的转换,而模板是完全匹配的吗?有没有办法确保我的数组函数被调用?
cppreference †声明:
具有普通默认构造函数的对象可以通过
reinterpret_cast在任何适当对齐的存储上使用来创建,例如在分配有的存储器上std::malloc.
这意味着以下是明确定义的代码:
struct X { int x; };
alignas(X) char buffer[sizeof(X)]; // (A)
reinterpret_cast<X*>(buffer)->x = 42; // (B)
Run Code Online (Sandbox Code Playgroud)
以下是三个问题:
X开始的生命周期是什么时候?如果在线(B),它是否被视为获取存储?如果在线(A),如果有一个分支(A)和(B)有条件地构建一个X或其他一些pod,Y怎么办?†请注意,这是一个旧链接.针对这个问题,措辞发生了变化.它现在写道:
但是,与C不同,通过简单地重新解释适当对齐的存储来创建具有普通默认构造函数的对象,例如分配的内存
std::malloc:placement-new是正式引入新对象并避免潜在的未定义行为所必需的.
使用 C++20'sconcept我注意到这std::unique_ptr似乎无法满足这个std::equality_comparable_with<std::nullptr_t,...>概念。从std::unique_ptr的定义来看,它应该在 C++20 中实现以下内容:
template<class T1, class D1, class T2, class D2>
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
template <class T, class D>
bool operator==(const unique_ptr<T, D>& x, std::nullptr_t) noexcept;
Run Code Online (Sandbox Code Playgroud)
这个要求应该实现对称比较nullptr——根据我的理解,这足以满足equality_comparable_with.
奇怪的是,这个问题似乎在所有主要编译器上都是一致的。以下代码被 Clang、GCC 和 MSVC 拒绝:
// fails on all three compilers
static_assert(std::equality_comparable_with<std::unique_ptr<int>,std::nullptr_t>);
Run Code Online (Sandbox Code Playgroud)
然而,同样的断言与std::shared_ptr被接受:
// succeeds on all three compilers
static_assert(std::equality_comparable_with<std::shared_ptr<int>,std::nullptr_t>);
Run Code Online (Sandbox Code Playgroud)
除非我误解了什么,否则这似乎是一个错误。我的问题是这是否是三个编译器实现中的巧合错误,还是 C++20 标准中的缺陷?
注意:如果这恰好是一个缺陷,我会标记这个语言律师 …
c++ ×10
c++11 ×3
c++17 ×3
c++-concepts ×2
c++20 ×2
arrays ×1
c++-faq ×1
c++14 ×1
dictionary ×1
memory ×1
pointers ×1
stdlaunder ×1