这段代码可以在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变量。
灵感来源:为什么 std::aligned_storage 在 C++23 中被弃用以及使用什么替代?
\n链接的提案P1413R3(不赞成使用std::aligned_storage)表示:
\n\n使用
\naligned_*调用未定义的行为(类型无法提供存储。)
这是指[intro.object]/3:
\n\n如果在与N \xe2\x80\x9d 类型的 \xe2\x80\x9carray或N \xe2 \ 类型 \xe2\x80\x9carray 的另一个对象e关联的存储中创建了完整对象 ([expr.new]) x80\x9d ([cstddef.syn]),该数组为创建的对象提供存储,如果: ...
\nunsigned charstd\xe2\x80\x8b::\xe2\x80\x8bbyte
然后,该标准在一些定义中继续使用术语“提供存储”,但我没有看到它在任何地方说使用不同类型作为新放置的存储(无法“提供存储”)会导致 UB 。
\n那么,问题是:std::aligned_storage当用于放置新时,是什么导致了UB?
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 确实有编译时格式字符串验证。他们只是不检查这个具体问题(过多的争论)。
我的同事今天向我展示了以下示例:
#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);打印1和2,如果您只调用其中之一。
如果您同时调用两者(按此顺序),则:
1 1。foo.2 2在发布版本中打印并在调试版本中发出类似的链接器错误(可能受增量链接的影响,未调查)。这里发生了什么?代码在我看来格式良好,但也许我错了?
从 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)
只是想知道,哪个编译器就在这里(如果有的话)?
考虑这个代码:
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++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。
标准是这样说的:
... attribute-specifier-seq [位于位置 (2)] 属于相应函数调用运算符或运算符模板的类型。
attribute-specifier-seq [位于位置 (1)] 属于相应的函数调用运算符或运算符模板。
“属于相应函数调用运算符的类型”让我感到困惑。我可以在这里放置哪些属性?这是否仅适用于特定于编译器的属性?如果是,这里可以使用哪些非标准属性?
显然,列表 (2) 早在 C++23 之前就已存在(该提案添加了列表 (1))。
我想使用 SDL2 制作游戏,但我无法编译和/或运行我的代码,请帮助!
众所周知,SDL2 很难设置,它通常是有抱负的游戏开发人员尝试使用的第一个库。
这篇文章旨在作为设置 SDL2 的常见问题的规范副本。
考虑以下代码:
#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++ ×10
c++20 ×2
c++23 ×2
lambda ×2
auto ×1
c ×1
c++-concepts ×1
c++17 ×1
fmt ×1
goto ×1
if-constexpr ×1
initializer ×1
namespaces ×1
sdl ×1
sdl-2 ×1
stdformat ×1
syntax ×1