当前的C ++草案在[ dcl.attr.contract.check ] p3中包含:
应该没有编程的方式来设置,修改或查询翻译单元的构建级别。
我不明白为什么建议不要允许查询合同级别。使用当前assert
宏,可以检测是否通过NDEBUG
宏使用了断言。
在某些情况下,查询合同级别很有用:
建议不要查询构建级别的背后原因是什么?
我在gcc上遇到了不会在clang上发生的错误
template<typename T>
int invoke_func(T a) {
return a;
}
bool test(int(*ptr)(int))
{
return ptr == invoke_func<int>;
}
Run Code Online (Sandbox Code Playgroud)
错误:
<source>: In function 'bool test(int (*)(int))':
<source>:9:19: error: assuming cast to type 'int (*)(int)' from overloaded function [-fpermissive]
return ptr == invoke_func<int>;
^~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
gcc是否有权拒绝此代码?
经过进一步测试后,替换invoke_func<int>
为&invoke_func<int>
gcc和clang的作品。
但是为什么&
当表达式不是这样的时候需要在这里int(*ptr)(int) = invoke_func<int>;
吗?
如果一切顺利,C ++ 20将具有新的consteval关键字和constexpr析构函数。遗憾的是,我目前所知没有编译器实现约束。以下代码将有效。
struct A {
constexpr ~A() {}
};
consteval A f() {
return A{};
}
void test() {
A a;
a = f(); // <-- here
}
Run Code Online (Sandbox Code Playgroud)
问题来自我标记的行A
,f
需要调用返回的临时对象的析构函数。但应在完整表达式的结尾处调用它。因此不在即时评估范围之内。
我没有从consteval和constexpr析构函数论文中找到任何明确禁止这样做的报价。但我看不出它怎么可能是正确的。
以下代码在C ++ 20中是否有效?此代码应如何处理?
注意:
在当代论文中,给出了这个例子。在这里,consteval函数在常量上下文之外被调用。
consteval int sqr(int n) {
return n*n;
}
constexpr int r = sqr(100); // Okay.
int x = 100;
int r2 = sqr(x); // Error: Call …
Run Code Online (Sandbox Code Playgroud) int test1(int a, int b) {
if (__builtin_expect(a < b, 0))
return a / b;
return b;
}
Run Code Online (Sandbox Code Playgroud)
被铛编译-O3 -march=native
到
test1(int, int): # @test1(int, int)
cmp edi, esi
jl .LBB0_1
mov eax, esi
ret
.LBB0_1:
mov eax, edi
cdq
idiv esi
mov esi, eax
mov eax, esi # moving eax back and forth
ret
Run Code Online (Sandbox Code Playgroud)
为什么eax
在之后来回移动idiv
?
gcc具有类似的行为,因此这似乎是有意的。
gcc -O3 -march=native
符合代码
test1(int, int):
mov r8d, esi
cmp edi, esi
jl .L4
mov eax, r8d
ret …
Run Code Online (Sandbox Code Playgroud) __builtin_is_constant_evaluated
是用于std::is_constant_evaluated
在clang和gcc的标准库中实现的内置函数。
在常量上下文中无效的代码通常也使优化程序难于常量折叠。
例如:
int f(int i) {
if (__builtin_is_constant_evaluated())
return 1;
else {
int* ptr = new int(1);
int i = *ptr;
delete ptr;
return i;
}
}
Run Code Online (Sandbox Code Playgroud)
发出gcc -O3
为:
f(int):
sub rsp, 8
mov edi, 4
call operator new(unsigned long)
mov esi, 4
mov rdi, rax
call operator delete(void*, unsigned long)
mov eax, 1
add rsp, 8
ret
Run Code Online (Sandbox Code Playgroud)
所以使用了优化器 __builtin_is_constant_evaluated() == 0
clang将其折叠为常数,但这是因为clang的优化器可以删除不需要的动态分配,而不是因为使用了__builtin_is_constant_evaluated() == 1
。
我知道这将__builtin_is_constant_evaluated()
定义实现的返回值,因为优化因一个编译器而异。但是仅当两个路径具有相同的可观察行为时,才应该使用is_constant_evaluated。
如果无法折叠,为什么优化器不使用__builtin_is_constant_evaluated() == 1 …
is it required by the standard to call non-trivial destructor when you know that in this specific case the destructor is a noop ?
is the code likely to be broken by compliers if the destructor is not called ?
the use case is a class that contain a dynamicly allocated pointer. by default this pointer is obtained by new
in the constructor. this class can also get its dynamicly allocated pointer from an allocator. the class keeps track of …
c++ memory-management lifetime language-lawyer explicit-destructor-call
为什么不std::decay
从函数指针中删除noexcept说明符?
例如,这符合c ++ 17
#include <type_traits>
template<typename>
struct is_noexcept {};
template<typename R, typename ... Arg>
struct is_noexcept<R(*)(Arg...)> : public std::false_type {};
template<typename R, typename ... Arg>
struct is_noexcept<R(*)(Arg...) noexcept> : public std::true_type {};
void test() noexcept {}
int main(){
void (*b)() noexcept = test;
static_assert(is_noexcept<decltype(b)>::value);
static_assert(is_noexcept<std::decay<decltype(b)>::type>::value);
}
Run Code Online (Sandbox Code Playgroud)