小编Tyk*_*ker的帖子

演绎指南可以有一个明确的(布尔)说明符吗?

标准的多个部分表明,推导指南不能具有显式说明符,而只能在其前面具有显式关键字。

喜欢:

temp.deduct.duide

演绎指南:

显式opt 模板名称parameter-declaration-clause)-> simple-template-id ;

请注意,该标准说:显式opt而不显式-说明符

或在dcl.fct.spec中

显式说明符,应仅在其类定义内的构造或转换函数的声明被使用; ...

但该标准还在over.match.class.deduct指出

如果函数或函数模板是从具有显式说明符的构造函数或推导中生成的,则每个这样的概念性构造函数均被视为具有相同的显式说明符

这句话暗示推导指南可以有一个明确的说明符

我没有看到为什么推理指南没有显式说明符的任何特殊原因。

是我对标准的理解还是标准本身的问题?

演绎指南可以有一个明确的(布尔)说明符吗?

c++ language-lawyer c++20

31
推荐指数
1
解决办法
688
查看次数

为什么建议不允许查询C ++ 20合同的合同级别?

当前的C ++草案在[ dcl.attr.contract.check ] p3中包含:

应该没有编程的方式来设置,修改或查询翻译单元的构建级别。

我不明白为什么建议不要允许查询合同级别。使用当前assert宏,可以检测是否通过NDEBUG宏使用了断言。

在某些情况下,查询合同级别很有用:

  • 添加其他变量以跟踪其他状态。
  • 在原子比较交换中转换原子存储以读取值。

建议不要查询构建级别的背后原因是什么?

c++ c++20

13
推荐指数
1
解决办法
222
查看次数

假设从gcc的重载函数转换为xxx类型时出错

我在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++ c++17

9
推荐指数
1
解决办法
307
查看次数

具有非平凡constexpr析构函数的约束函数重现对象

如果一切顺利,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)

问题来自我标记的行Af需要调用返回的临时对象的析构函数。但应在完整表达式的结尾处调用它。因此不在即时评估范围之内。

我没有从constevalconstexpr析构函数论文中找到任何明确禁止这样做的报价。但我看不出它怎么可能是正确的。

以下代码在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)

c++ language-lawyer c++20

6
推荐指数
1
解决办法
122
查看次数

编译器在eax上来回移动

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)

c++ assembly gcc x86-64 micro-optimization

5
推荐指数
1
解决办法
166
查看次数

为什么不允许优化器在“恒定上下文”中折叠?

__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 …

c++ optimization c++20

5
推荐指数
1
解决办法
761
查看次数

is it required to call a non-trivial destructor when it is a noop?

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

4
推荐指数
1
解决办法
117
查看次数

no除了不被腐烂去除

为什么不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)

c++ c++17

0
推荐指数
1
解决办法
78
查看次数