考虑以下代码:
struct A {};
template <typename T> struct B
{
B(T) {}
auto foo() {return B(A{});} // error: no matching function for call to 'B<int>::B(A)'
};
auto foo() {return B(A{});} // compiles
int main()
{
foo();
B b(0);
b.foo();
}
Run Code Online (Sandbox Code Playgroud)
我理解为什么B::foo()不编译:内部struct B<T>,B(作为注入类名称)意味着B<T>除非它被明确地用作模板.在这种情况下,这会阻止类模板参数推断.
假设我不能这样做,auto foo() {return B<A>(A{});}因为我的实际代码依赖于用户提供的略微复杂的演绎指南.
问题是:在构造B内部时如何强制类模板参数推导B::foo?
我希望我不会错过一些明显的东西.
(这个问题最初是由俄罗斯 SO的另一位用户提出的。我在此处重新发布并稍作更改,以增加曝光率。)
考虑这个代码:
#include <map>
#include <variant>
void operator&&(std::variant<int>, std::variant<int>) {}
int main()
{
std::map<int, int> vals;
vals.find(42);
}
Run Code Online (Sandbox Code Playgroud)
Clang(使用 libstdc++ 和 libc++)和 MSVC 编译它没有问题。
Hovewer、GCC 11.1 和更新版本(包括主干)给出了这个: Run on gcc.godbolt.org
#include <map>
#include <variant>
void operator&&(std::variant<int>, std::variant<int>) {}
int main()
{
std::map<int, int> vals;
vals.find(42);
}
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?
编辑:
我们的operator==重载对于名称查找应该是不可见的<variant>(除了 ADL,这里不涉及),所以这绝对是一个 GCC 错误。
@rustyx 发现GCC 错误 #51577,看起来非常相似。但是还有更多,因为该错误是在 GCC 4.7.0 中引入的,而上面的代码仅在 11.1 和更新版本中出现。
考虑以下代码:
union U
{
int a;
float b;
};
int main()
{
U u;
int *p = &u.a;
*(float *)p = 1.0f; // <-- this line
}
Run Code Online (Sandbox Code Playgroud)
我们都知道联合字段的地址通常是相同的,但是我不确定它是否是定义良好的行为来做这样的事情.
因此,问题是:在上面的代码中,如何转换和取消引用指向union字段的指针是合法且定义明确的行为吗?
PS我知道它比C++更多C,但我试图理解它是否在C++中是合法的,而不是C.
众所周知,返回指向堆栈变量的指针通常是一个坏主意:
int* foo() {
int i = 0;
return &i;
}
int main() {
int* p = foo();
}
Run Code Online (Sandbox Code Playgroud)
在上面的例子中,我的理解是 被int破坏了,p悬空指针也被破坏了。
我想知道这在多大程度上适用于 C++20 新引入的协程:
generator<span<byte>> read(stream& s) {
array<byte, 4096> b;
while (s.is_open()) {
const size_t n = s.read_some(b);
co_yield span(b, n);
}
}
int main() {
stream s;
for (span<byte> v : read(s)) {
/* ... */
}
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,read协程生成span本地缓冲区的视图b。在内部,该视图存储一个指向缓冲区的指针。v当与范围循环体一起使用时,该指针是否会悬空for?
对于上下文,第二个示例中的协程代码是根据我自己的项目中的代码建模的。在那里,AddressSanitizer 以“释放后使用”错误结束程序。通常我认为这足以回答我的问题,但由于此时协程开发仍在进行中(我的项目正在使用boost::asio::experimental::coro,强调“实验”),我想知道该错误是否是由以下错误引起的generator …
考虑x声明中是否int x;有表达式。
我以前以为肯定不是,但是语法id-expression这里把变量名称为an。
那么有人可能会争辩说 onlyexpression是一个表达式,而不是??-expression。但在 中1 + 2,既不匹配1也不2匹配,因为它们分别是additive-expression和multiplicative-expression,而不是expressions。但常识告诉我们,这些也应该被称为表达式。
我们可以决定any ??-expression(包括expression)是一个表达式,但声明中的变量名也匹配。
我们可以将表达式定义为 any ??-expressionexcept id-expression,但这感觉相当随意。
表达式的正确语法定义是什么?其声明中的变量名是否是表达式?
我刚刚更新MinGW的使用mingw-get-setup状态,我无法构建一个包含点儿什么<cmath>,如果我使用任何大于头-O0用-std=c++1y.(我也试过c++11和c++98)我得到象这样的错误之一:
g++.exe -pedantic-errors -pedantic -Wextra -Wall -std=c++1y -O3 -c Z:\Projects\C++\L6\src\events.cpp -o obj\src\events.o
In file included from z:\lander\mingw\lib\gcc\mingw32\4.8.1\include\c++\cmath:44:0,
from Z:\Projects\C++\L6\src\utils.h:4,
from Z:\Projects\C++\L6\src\events.cpp:10:
z:\lander\mingw\include\math.h: In function 'float hypotf(float, float)':
z:\lander\mingw\include\math.h:635:30: error: '_hypot' was not declared in this scope
{ return (float)(_hypot (x, y)); }
Run Code Online (Sandbox Code Playgroud)
我这边有什么不对劲吗?
或mingw repo的版本被窃听?如果是这样,这个标题有什么快速解决方法吗?
这是我想要做的:
template <typename T> void f(DisableDeduction<T> obj) {std::cout << obj;}
// Here DisableDeduction<T> aliases T, but in a such way
// that would prevent compiler from deducing T based
// on provided argument.
/* ... */
f<int>(1); // Works.
f(1); // Error, can't deduce template parameter based on argument.
Run Code Online (Sandbox Code Playgroud)
这就是我目前实现它的方式:
template <typename T> struct DisableDeduction_Internal {using type = T;};
template <typename T> using DisableDeduction = typename DisableDeduction_Internal<T>::type;
Run Code Online (Sandbox Code Playgroud)
它完美地工作(如上所述),但它引入了一个额外的帮助器类型.
但是我可以在没有额外类型的情
Clang 8发行说明中有以下内容:
- 允许在MinGW上使用Address Sanitizer和Undefined Behavior Sanitizer。
但是,我无法弄清楚如何正确使用它们。
我将Clang 8.0.0与MSYS2 MinGW GCC结合使用。确切的细节在问题的底部。
我正在尝试编译以下最少的代码:
1.cpp
#include <iostream>
int main()
{
// Testing ubsan
int x = 0x7fffffff;
x++;
std::cout << x << std::endl;
// Testing asan
int *y = new int;
delete y;
std::cout << *y << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
以下是结果-fsanitize=address:
# /z/Lander/LLVM/bin/clang++ -target x86_64-w64-windows-gnu -fsanitize=address 1.cpp
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic-x86_64.dll.a: No such file or directory
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic_runtime_thunk-x86_64.a: No such file or directory
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic_runtime_thunk-x86_64.a: No …Run Code Online (Sandbox Code Playgroud) 下面是一个例子:
#include <cstddef>
#include <iostream>
struct A
{
char padding[7];
int x;
};
constexpr int offset = offsetof(A, x);
int main()
{
A a;
a.x = 42;
char *ptr = (char *)&a;
std::cout << *(int *)(ptr + offset) << '\n'; // Well-defined or not?
}
Run Code Online (Sandbox Code Playgroud)
我一直认为它是明确定义的(否则有什么意义offsetof),但不确定。
最近有人告诉我它实际上是UB,所以我想一劳永逸地弄清楚。
上面的例子是否会导致UB?如果将类修改为非标准布局,是否会影响结果?
如果是 UB,是否有任何解决方法(例如申请std::launder)?
整个主题似乎都没有实际意义且没有具体说明。
以下是我能找到的一些信息:
是否添加到“char *”指针 UB,当它实际上并不指向 char 数组时?- 2011 年,CWG 确认允许我们通过unsigned char指针检查标准布局对象的表示。
char可以使用指针代替,常识说它可以。不清楚是否std::launder需要将来自 C++17 的凝视应用于转换的结果(unsigned char …
在 c++20 中玩弄文字、非类型模板参数,我发现 g++ 和 clang++ 不同意以下代码。
#include <algorithm>
template<size_t N>
struct StringLiteral {
constexpr StringLiteral(const char (&str)[N]) {
std::copy_n(str, N, value);
}
char value[N];
};
template <typename T, StringLiteral Name>
struct named{};
template <typename T>
struct is_named: std::false_type{};
template <typename T, size_t N, StringLiteral<N> Name>
struct is_named<named<T, Name>>: std::true_type{};
// This will fail with g++
static_assert(is_named<named<int, "ciao">>::value == true);
Run Code Online (Sandbox Code Playgroud)
在 Godbolt 上实时查看:https ://godbolt.org/z/f3afjd
首先也是最重要的,我什至不确定我是否以正确的方式做这件事:它是与泛型StringLiteral<N>类型匹配的方式,还是不是?如果不是,正确的方法是什么?
而且,为什么编译器不同意呢?谁有错误?
编辑:发现删除size_t N部分特化中的参数使两个编译器都同意,结果是预期的。像这样:
template <typename T, StringLiteral …Run Code Online (Sandbox Code Playgroud)