我正在阅读B. Stroustrup的关于C++ 17的思考合同,并协助一个小小的演讲,谈论他们,但我不确定我是否真的理解它们.
所以我有一些问题,如果有可能用一些例子来说明它们:
合同是否是经典的更好替代品,assert()它们应该一起使用吗?对于软件开发人员来说,简单的合同是什么?
合同会对我们处理异常的方式产生影响吗?如果是,我们应该如何使用例外和合同?
使用合同是否意味着执行时的开销?我们是否允许在发布代码上停用它们?
从提案N4415编辑:
可以编写Vector类的索引操作符的前置条件合约:
T& operator[](size_t i) [[expects: i < size()]];类似地,ArrayView类的构造函数上的条件后约定可表示为:
ArrayView(const vector<T>& v) [[ensures: data() == v.data()]];
在答案/sf/answers/49319791/中,引用了Stroustrup:
C++显然允许delete的实现将左值操作数归零,我曾希望实现会这样做,但这个想法似乎并没有受到实现者的欢迎.
但是,我没有在标准中找到这个明确的陈述.目前的标准草案(N4659)中有一部分可以用这种方式解释:
6.7:
当达到存储区域的持续时间结束时,表示该存储区域的任何部分的地址的所有指针的值变为无效指针值(6.9.2).通过无效指针值间接并将无效指针值传递给释放函数具有未定义的行为.对无效指针值的任何其他使用都具有实现定义的行为.
脚注:某些实现可能会定义复制无效指针值会导致系统生成的运行时错误
因此,在a之后delete ptr;,ptrs值变为无效指针值,并且使用此值具有实现定义的行为.但是,它并没有说ptr允许改变价值.
这可能是一个哲学问题,如果一个人不能使用它的价值,怎么能决定一个价值发生了变化呢?
6.9:
对于普通可复制类型T的任何对象(基类子对象除外),无论对象是否保持类型T的有效值,构成对象的基础字节(4.4)都可以复制到char数组中, unsigned char,或std :: byte(21.2.1).43如果将该数组的内容复制回对象,该对象应随后保持其原始值.
所以,似乎它对memcpy一个char数组的无效指针值是有效的(取决于哪个语句是"更强",6.7或6.9.对我来说,6.9似乎更强).
这样,我可以通过以下方式检测到指针值已被改变delete:memcpy指向deleteto char数组之前和之后的值,然后比较它们.
所以,据我所知,6.7 delete不允许允许修改其参数.
是否允许删除修改其参数?
看看这里的评论:https: //stackoverflow.com/a/45142972/8157187
这是一个不太可能但仍然可能的现实世界代码,其中重要的是:
SomeObject *o = ...; // We have a SomeObject
// This SomeObject is registered into someHashtable, with its memory address
// The hashtable interface is C-like, it handles opaque keys (variable length unsigned char arrays)
delete o; …Run Code Online (Sandbox Code Playgroud) 我需要一个类型特征,如果给定的类型派生自任何东西,则为true,否则为false.
例如:
template<class T>
struct is_inherit
//... logic of inheritance detection
;
template<class T>
void AppLogic(){
if constexpr(is_inherit<T>::value) {
puts("T has base");
//...
} else {
puts("T doesn't have base");
//...
}
}
struct A {};
struct C {};
struct B: C {};
int main() {
AppLogic<A>(); // print: T doesn't have base
AppLogic<B>(); // print: T has base
}
Run Code Online (Sandbox Code Playgroud)
是否有可能以某种方式实现"is_inherit"特征结构?
为什么?
我正在为Windows x64开发一个手动堆栈框架构建器.根据https://docs.microsoft.com/en-us/cpp/build/return-values-cpp文档,如果是类型:
然后它的返回值在RAX寄存器中,否则该函数有一个我必须检测和处理的隐藏参数.
这曾经是C++ 03 POD的定义,但是在C++ 11中这改变了:
由于C++ 11标准中的定义已更改,因此我们不建议您使用 …
在C++ 17中,您是否可以修改constexpr函数中的全局变量?
#include <iostream>
int global = 0;
constexpr int Foo(bool arg) {
if (arg) {
return 1;
}
return global++;
}
int main() {
std::cout << global;
Foo(true);
std::cout << global;
Foo(false);
std::cout << global;
}
Run Code Online (Sandbox Code Playgroud)
我不希望你能够,但clang 6允许它:https://godbolt.org/g/UB8iK2
但是,海湾合作委员会不会:https://godbolt.org/g/ykAJMA
哪个编译器正确?
考虑:
static constexpr unsigned num_points{ 7810 };
std::array< double, num_points > axis;
for (int i = 0; i < num_points; ++i)
{
axis[i] = 180 + 0.1 * i;
}
Run Code Online (Sandbox Code Playgroud)
axis是全类常量。我想避免像其他任何全局变量一样初始化它。可以在编译时完成吗?
这是完整的最后一堂课:
// https://www.nist.gov/pml/atomic-spectroscopy-compendium-basic-ideas-notation-data-and-formulas/atomic-spectroscopy
// https://www.nist.gov/pml/atomic-spectra-database
struct Spectrum
{
static constexpr unsigned _num_points{ 7810 };
using Axis = std::array< double, _num_points >;
static constexpr Axis _x{ [] () // wavelength, nm
{
Axis a {};
for( unsigned i = 0; i < _num_points; ++i )
{
a[ i ] …Run Code Online (Sandbox Code Playgroud) 在编写一些代码时,我遇到了一个问题,即我设置的值设置错误。我最终找到了罪魁祸首,并在测试时发现它在C ++ 14和C ++ 17上的表现有所不同。代码如下:
#include <stdio.h>
#include <cstdint>
#include <cstring>
int main()
{
uint8_t *p = new uint8_t[3];
memset(p, 0x00, 1);
p++;
memset(p, 0xF0, 1);
p++;
memset(p, 0xFF, 1);
p--;
p--;
// This line in particular
*p++ = *p;
*p++ = 0x0F;
p--;
p--;
printf("Position 0 has value %u\n", *p);
p++;
printf("Position 1 has value %u\n", *p);
p++;
printf("Position 2 has value %u\n", *p);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在C ++ 14上它打印:
Position 0 has value 240
Position 1 has value …Run Code Online (Sandbox Code Playgroud) 在 C++17 中,如何使用可选元素声明和初始化成对(或元组)向量?
std::vector<std::pair<int, optional<bool> > > vec1 = { {1, true},
{2, false},
{3, nullptr}};
Run Code Online (Sandbox Code Playgroud)
我有一对,其中第二个元素可能为空/可选。
回顾关于折叠的C++ 17 论文(以及cppreference),我很困惑为什么选择只与运营商合作?乍一看似乎(... + args)只是通过+在元素之间推一个标记来扩展它更容易args,但我不相信这是一个伟大的决定.
为什么二元lambda表达式不能同样工作并遵循与上面相同的扩展?对我来说,在不支持任意可调用语言的情况下将折叠语法添加到语言中是很不可思议的,语法是否允许使用我只是没有看到的方法?
更新:这适用于min()具有clang 的可变函数
template <typename T>
struct MinWrapper {
const T& obj;
};
template <typename T, typename U, typename V=std::common_type_t<T,U>>
constexpr MinWrapper<V> operator%(
const MinWrapper<T>& lhs, const MinWrapper<U>& rhs) {
return {lhs.obj < rhs.obj ? lhs.obj : rhs.obj};
}
template <typename... Ts>
constexpr auto min(Ts&&... args) {
return (MinWrapper<Ts>{args} % ...).obj;
}
Run Code Online (Sandbox Code Playgroud) 在JavaScript ES6中,有一种称为解构的语言功能.它也存在于许多其他语言中.
在JavaScript ES6中,它看起来像这样:
var animal = {
species: 'dog',
weight: 23,
sound: 'woof'
}
//Destructuring
var {species, sound} = animal
//The dog says woof!
console.log('The ' + species + ' says ' + sound + '!')
Run Code Online (Sandbox Code Playgroud)
我可以在C++中做些什么来获得类似的语法并模拟这种功能?
前几天进行一些模板元编程时遇到了奇怪的事情。基本上可以归结为这个断言没有(正如我期望的那样)通过。
static_assert(std::is_same_v<void(), std::remove_reference_t<void()&>>);
Run Code Online (Sandbox Code Playgroud)
起初我以为我在定义函数引用时犯了语法错误,但是这个断言通过了,表明事实并非如此。
static_assert(std::is_same_v<void()&, void()&>);
Run Code Online (Sandbox Code Playgroud)
我还尝试实现remove_reference自己从cppreference复制源,但这也不起作用。这里发生了什么?
c++ ×10
c++17 ×10
assertion ×1
c++14 ×1
compile-time ×1
constexpr ×1
fold ×1
inheritance ×1
javascript ×1
optional ×1
std-pair ×1
stdarray ×1
templates ×1
type-traits ×1
types ×1
vector ×1