小编Hol*_*Cat的帖子

在lambda内部捕获的Constexpr变量失去了其解释性

这段代码可以在g ++(coliru)中很好地编译,但是在MSVC(Godbolt和我的VS2017)中却不能。

#include <type_traits>
#include <iostream>
template<class T> void f(){
    constexpr bool b=std::is_same_v<T,int>; //#1
    auto func_x=[&](){
        if constexpr(b){ //#error
        }else{
        }
    };
    func_x();
}
int main(){
    f<int>();
}
Run Code Online (Sandbox Code Playgroud)

(6):错误C2131:表达式未求值为常数
(6):注意:失败是由于在其生命周期之外读取变量导致的
(6):注意:请参见'this'的用法

哪一个(g ++或MSVC)错了?“ 请参阅'this'的用法
是什么??this

在保留编译时保证的同时如何解决呢?

在我的真实情况下,b (#1)一个复杂的语句取决于其他一些constexpr变量。

c++ lambda language-lawyer c++17 if-constexpr

19
推荐指数
2
解决办法
867
查看次数

为什么使用 `std::aligned_storage` 据称会因无法“提供存储”而导致 UB?

灵感来源:为什么 std::aligned_storage 在 C++23 中被弃用以及使用什么替代?

\n

链接的提案P1413R3(不赞成使用std::aligned_storage)表示:

\n
\n

使用aligned_*调用未定义的行为(类型无法提供存储。)

\n
\n

这是指[intro.object]/3

\n
\n

如果在与N \xe2\x80\x9d 类型的 \xe2\x80\x9carray或N \xe2 \ 类型 \xe2\x80\x9carray 的另一个对象e关联的存储中创建了完整对象 ([expr.new]) x80\x9d ([cstddef.syn]),该数组为创建的对象提供存储,如果: ... unsigned char std\xe2\x80\x8b::\xe2\x80\x8bbyte

\n
\n

然后,该标准在一些定义中继续使用术语“提供存储”,但我没有看到它在任何地方说使用不同类型作为新放置的存储(无法“提供存储”)会导致 UB 。

\n

那么,问题是:std::aligned_storage当用于放置新时,是什么导致了UB?

\n

c++ language-lawyer c++23

19
推荐指数
2
解决办法
1563
查看次数

如何在编译时检查所有参数是否有足够的“{}”占位符?

std::format有一个(编译时和运行时)格式字符串验证,但此验证中不包括的一件事是是否有足够的{}占位符用于所有参数(过多的参数将被默默忽略)。

我认为这在某些罕见的情况下可能很有用(例如,如果您生成格式字符串),但我不需要它,并且因此我遇到了一些错误。

我可以做些什么来检查这个编译时间吗?可能通过包装std::format我自己的函数。

例子:

#include <format>
#include <iostream>

int main()
{
    std::cout << std::format("{} {}", 1, 2, 3, 4, 5) << '\n'; // Prints `1 2`, no error!
}
Run Code Online (Sandbox Code Playgroud)

注意: std::format 确实有编译时格式字符串验证。他们只是不检查这个具体问题(过多的争论)。

c++ fmt stdformat

19
推荐指数
1
解决办法
301
查看次数

在定义更受约束的版本之前和之后调用函数模板会产生奇怪的结果

我的同事今天向我展示了以下示例:

Run on gcc.godbolt.org

#include <concepts>
#include <iostream>

template <typename T>
void foo(T)
{
    std::cout << "1\n";
}

template <typename T>
void bar(T value)
{
    foo(value);
}

void foo(std::same_as<int> auto)
{
    std::cout << "2\n";
}
Run Code Online (Sandbox Code Playgroud)

在这里,bar(42);并分别foo(42);打印12如果您只调用其中之一。

如果您同时调用两者(按此顺序),则:

  • 叮当印1 1
  • GCC 发出链接器错误,抱怨foo.
  • MSVC2 2在发布版本中打印并在调试版本中发出类似的链接器错误(可能受增量链接的影响,未调查)。

这里发生了什么?代码在我看来格式良好,但也许我错了?

c++ language-lawyer c++20

18
推荐指数
1
解决办法
248
查看次数

C++20 中概念化的“operator auto”

从 C++20 开始,我们可以在auto关键字前面加上概念的名称来限制可能的类型。特别是这种组合在类转换中是可能的operator auto,例如

template <typename T> concept x = true;

struct S
{
    operator x auto() { return 2; }
    operator auto() { return 1; }
};

int main() { return S{}.operator x auto(); }
Run Code Online (Sandbox Code Playgroud)

但是 Clang 是唯一接受整个程序的编译器,但是main()返回1(而不是2我预期的那样),演示:https : //gcc.godbolt.org/z/b16jYGa81

GCC 接受结构体定义,但拒绝编译S{}.operator x auto().

即使struct S出现错误,MSVC 也拒绝接受:

error C2535: 'S::operator auto(void)': member function already defined or declared
Run Code Online (Sandbox Code Playgroud)

只是想知道,哪个编译器就在这里(如果有的话)?

c++ auto c++-concepts c++20

18
推荐指数
1
解决办法
612
查看次数

跳过变量初始化格式错误还是会导致未定义的行为?

考虑这个代码:

void foo()
{
    goto bar;
    int x = 0;
    bar: ;
}
Run Code Online (Sandbox Code Playgroud)

GCC 和 Clang拒绝它,因为跳转到bar:绕过变量初始化。MSVC 根本不抱怨(除非使用xafterbar:导致警告)。

我们可以用 a 做类似的事情switch

void foo()
{
    switch (0)
    {
        int x = 0;
        case 0: ;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在所有三个编译器都发出错误

这些片段格式不正确吗?或者他们会导致UB?

我曾经认为两者都是格式错误的,但我找不到标准的相关部分。[stmt.goto]不说这事,而且也不[stmt.select]

c++ goto initializer variable-declaration language-lawyer

17
推荐指数
1
解决办法
839
查看次数

在 lambda 中,第二个属性列表有什么作用?

C++23 允许[[...]]lambda 表达式中的属性:

auto lambda = [] [[nodiscard]]
{
    return 42;
};
Run Code Online (Sandbox Code Playgroud)

但是语法有两个属性列表,大致在参数列表之前和之后:

auto lambda = [] [[nodiscard]] () [[deprecated]]
//               (1)~~~~~~~~~~    (2)~~~~~~~~~~~  // (2) seems to have no effect here
{
    return 42;
};
Run Code Online (Sandbox Code Playgroud)

这两个列表适用于不同的事物,但我无法弄清楚第二个列表的用途,以及我可以在此处放置哪些属性。对于我在 (2) 中尝试的任何属性,Clang 警告:'...' attribute cannot be applied to types

标准是这样说的:

[expr.prim.lambda.closure]/6

... attribute-specifier-seq [位于位置 (2)] 属于相应函数调用运算符或运算符模板的类型。

attribute-specifier-seq [位于位置 (1)] 属于相应的函数调用运算符或运算符模板。

“属于相应函数调用运算符的类型”让我感到困惑。我可以在这里放置哪些属性?这是否仅适用于特定于编译器的属性?如果是,这里可以使用哪些非标准属性?

显然,列表 (2) 早在 C++23 之前就已存在(该提案添加了列表 (1))。

c++ syntax lambda c++23 c++-attributes

17
推荐指数
1
解决办法
831
查看次数

如何在我的程序中正确使用 SDL2?

我想使用 SDL2 制作游戏,但我无法编译和/或运行我的代码,请帮助!

众所周知,SDL2 很难设置,它通常是有抱负的游戏开发人员尝试使用的第一个库。

这篇文章旨在作为设置 SDL2 的常见问题的规范副本。

c c++ sdl sdl-2

16
推荐指数
1
解决办法
4303
查看次数

在函数实现中使用命名空间

在C++中,我可以using namespace std;在函数实现文件中使用声明吗?

c++ namespaces

14
推荐指数
3
解决办法
2万
查看次数

标准是否将模板类的非模板成员视为"模板"本身?

考虑以下代码:

#include <type_traits>

template <typename T> struct A
{
    static_assert(!std::is_same_v<int, T>);
};

template<typename T> struct B
{
    void foo()
    {
        A<int>{};
    }
};

int main() {}
Run Code Online (Sandbox Code Playgroud)

它来自俄罗斯StackOverflow上的这个问题,它询问它是否有效.

我试图引用这个:

[temp.res] /8.1

8可以在任何实例化之前检查模板的有效性.[注意:知道哪些名称是类型名称允许以这种方式检查每个模板的语法.- 尾注] 如果出现以下情况,该程序格式错误,无需诊断:

(8.1) - 不能为模板中的模板或子语句生成有效的专门化,并且模板中的constexpr if语句未实例化,或者

...

(强调我的)

由于无法生成有效的专业化foo(),因此我推断该片段格式不正确,NDR.

但我被告知[temp.res]/8.1不适用,因为foo()它本身不是模板成员函数.

cppreference调用模板类"模板化实体"的非模板成员函数,但似乎不清楚它们本身是否可以被视为模板.

因此,问题是:标准是否认为模板类的非模板成员本身就是"模板"?

c++ language-lawyer

14
推荐指数
1
解决办法
232
查看次数