下面的代码编译罚款与铛3.5.0,但不进行编译GCC 4.9.0(带-Wall -Wextra -pedantic-errors标志和任何的-std=c++03,-std=c++11和-std=c++14标志):
struct S
{
S(const float(&)[12])
{
}
};
float v[12];
S f()
{
return v;
}
int main()
{
}
Run Code Online (Sandbox Code Playgroud)
MS VC 2013也 编译了这段代码.
哪种编译器是正确的,什么是符合标准的行为?
编译一些代码,我遇到了编译器错误,这对我来说似乎很奇怪,并且与继承,嵌套类,使用声明和访问修饰符有关.
基本上,目的是使派生类型公开基类型的嵌套受保护类.
以下简短示例来说明问题:
class Base
{
protected:
struct Nested
{
enum value_enum
{
val = 0,
val2,
val3
};
};
};
class Derived : public Base
{
public:
using Base::Nested;
};
int main(int argc, char** argv)
{
//Base::Nested aa; // error, as (I) expected
//Base::Nested::value_enum ab; // error, as (I) expected
Derived::Nested ba; // works, as (I) expected
Derived::Nested::value_enum bb; // MSVC error, as (I) did not expect
return 0;
}
Run Code Online (Sandbox Code Playgroud)
看到现场.
MSVC11(v11.00.61030)对此代码进行了阻塞,并出现以下错误:
错误C2248:'Base :: Nested':无法访问类'Base'中声明的受保护结构
GCC和Clang都正确地编译了这个,因此如果没有引用标准中相关部分的能力,我认为这是一个MSVC错误.
有没有办法解决这个与MSVC?
c++ access-modifiers nested-class compiler-bug visual-studio-2012
我试图理解为什么我使用两个应该与我等效的模板得到不同的行为
给定
template<template<typename...> class TT, typename T1, typename T2>
class A {};
Run Code Online (Sandbox Code Playgroud)
is_a是通用版本
template<typename T>
struct is_a : std::false_type
{
};
template<template<typename...> class TT, typename... T>
struct is_a<A<TT, T...>> : std::true_type
{
};
Run Code Online (Sandbox Code Playgroud)
is_a2是手动扩展为2种类型而不是参数包的版本
template<typename T>
struct is_a2 : std::false_type
{
};
template<template<typename...> class TT, typename T1, typename T2>
struct is_a2<A<TT, T1, T2>> : std::true_type
{
};
Run Code Online (Sandbox Code Playgroud)
我希望当 A 用 3 个参数实例化时,这 2 个版本的行为相同,但事实并非如此
参见代码编译https://wandbox.org/permlink/MjSwFLvWmH0n1QLk
我希望is_a在任何is_a2可以工作的地方工作。
这是我应该报告的编译器错误吗?
编辑
显然这适用于 clang https://wandbox.org/permlink/9n5pXUGtBa8cAvFw
c++ templates language-lawyer compiler-bug template-meta-programming
下面的示例代码从lambda函数打印值,该函数简单地递增并返回静态局部计数器变量的值.
它使用gcc和clang C++ 17进行打印0,1和2,3预期.但是在Visual Studio Community 2017 15.9.3中没有/std:c++17设置 - 它打印0,0而2,3不是.
#include <iostream>
int main() {
auto f = [] {
static int i = 0;
return i++;
};
const int v1 = f(); // Expect v1 = 0
const int v2 = f(); // Expect v2 = 1
// Prints the wrong values (MSVC 15.9.3 with /std:c++17)
std::cout << v1 << "," << v2 << std::endl; // Expect "0,1", prints …Run Code Online (Sandbox Code Playgroud) 以下代码片段格式正确吗?
struct A { ~A() = delete; };
A *pa{new A{}};
class B { ~B() = default; };
B *pb{new B{}};
Run Code Online (Sandbox Code Playgroud)
A乍一看,B似乎从未使用过的已删除 dtor和私有显式默认 dtor从未使用过(有意的内存泄漏,如果您愿意的话),这可以说是格式良好的。
Clang 接受各种编译器和 C++ 版本(C++11 到 C++2a)的程序。
另一方面,GCC 拒绝针对各种编译器和 C++ 版本的程序。
Run Code Online (Sandbox Code Playgroud)struct A { ~A() = delete; }; A *pa{new A{}}; // GCC error: use of deleted function 'A::~A()' class B { ~B() = default; }; B *pb{new B{}}; // GCC error: 'B::~B()' is private within this context
(如果格式正确;在我提交错误报告之前:是否有针对此极端情况的任何开放的 GCC 错误报告?我自己搜索了 GCC:s bugzilla 无济于事。) …
我一直在试图理解std::nullopt_t不允许DefaultConstructible在 C++17(引入它的地方)及更高版本中的基本原理,并在此过程中解决了一些编译器差异混淆。
考虑以下违反规范的(它是DefaultConstructible)实现nullopt_t:
struct nullopt_t {
explicit constexpr nullopt_t() = default;
};
Run Code Online (Sandbox Code Playgroud)
它是 C++11 和 C++14(无用户提供的构造函数)中的聚合,但不是 C++17(构造函数explicit)和 C++20(用户声明的构造函数)中的聚合。
现在考虑以下示例:
struct S {
constexpr S() {}
S(S const&) {}
S& operator=(S const&) { return *this; } // #1
S& operator=(nullopt_t) { return *this; } // #2
};
int main() {
S s{};
s = {}; // GCC error: ambiguous overload for 'operator=' (#1 and #2)
}
Run Code Online (Sandbox Code Playgroud)
这在 …
考虑以下代码(编译器资源管理器链接),在 gcc 和 clang 下编译并进行-O3优化:
#include <arm_neon.h>
void bug(int8_t *out, const int8_t *in) {
for (int i = 0; i < 2; i++) {
int8x16x4_t x;
x.val[0] = vld1q_s8(&in[16 * i]);
x.val[1] = x.val[2] = x.val[3] = vshrq_n_s8(x.val[0], 7);
vst4q_s8(&out[64 * i], x);
}
}
Run Code Online (Sandbox Code Playgroud)
注意:这是一个问题的最小可重现版本,该问题出现在我实际的、更复杂的代码的许多不同函数中,其中充满了执行与上面完全不同的操作的算术/逻辑/排列指令。请不要批评和/或建议执行上述代码的不同方法,除非它对下面讨论的代码生成问题有影响。
clang 生成正常的代码:
bug(signed char*, signed char const*): // @bug(signed char*, signed char const*)
ldr q0, [x1]
sshr v1.16b, v0.16b, #7
mov v2.16b, v1.16b
mov v3.16b, v1.16b
st4 { v0.16b, …Run Code Online (Sandbox Code Playgroud) 我几乎可以肯定以下是 Visual Studio 编译器的错误,但很难相信我决定在这里仔细检查:
struct A {
constexpr virtual int f() { return 0; }
};
struct B : A {
constexpr auto f() { return 1.1; }
};
constexpr int g() {
B b;
A & a = b;
return a.f();
}
static_assert( g() != 1 );
static_assert( g() == 1.1 );
Run Code Online (Sandbox Code Playgroud)
g()声明为返回int类型的函数通过编译时检查g() == 1.1意味着g()实际上返回一个double值。此行为在最新的 MSVC 编译器中可以重现,在线演示: https: //gcc.godbolt.org/z/6sGET7773
由于B::f()声明不能包含auto返回类型,程序是否存在格式错误?
考虑声明一个不受约束的ns::operator*. using namespace ns在块作用域中并调用函数之后foo<T>,clangns::operator*在读取内部基于范围的循环的迭代器时使用foo。没有其他类型ns涉及其他类型,因此 ADL 应该不会产生任何候选者。
在以下示例中,static_assert失败并显示消息:
错误:由于要求 'std::is_same_v<const int &, const custom_type &>',静态断言失败
汇编代码显示这ns::operator*是由 clang 使用的。gcc 和 msvc 的断言都通过了!
namespace ns {
template <typename T>
constexpr auto operator*(T&& /*value*/) {
struct custom_type {};
return custom_type{};
};
} // namespace ns
template <typename T>
constexpr void foo() {
std::vector<T> vec{};
for (const auto& curr : vec) {
static_assert(std::is_same_v<const T&, decltype(curr)>);
}
}
int main() { …Run Code Online (Sandbox Code Playgroud) template <typename T>
inline constexpr int a = 1;
static_assert(&a<void>, "");
Run Code Online (Sandbox Code Playgroud)
这不会在gcc 9.2上进行编译,但是会在clang和msvc上进行编译。
Gcc抱怨用于的表达式static_assert不是常量表达式。
The code compiles after removing template, removing inline, or removing address-of operator.
Is this a gcc bug?
compiler-bug ×10
c++ ×9
gcc ×5
c++17 ×2
templates ×2
visual-c++ ×2
arm64 ×1
c ×1
c++11 ×1
c++14 ×1
clang ×1
constexpr ×1
namespaces ×1
neon ×1
nested-class ×1
using ×1