小编Hol*_*Cat的帖子

GCC接受`constexpr struct {} s;`但Clang拒绝它.谁是对的?

以下代码与GCC编译良好:

constexpr struct {} s;
Run Code Online (Sandbox Code Playgroud)

但Clang拒绝了它,出现以下错误:

错误:没有用户提供的默认构造函数,默认初始化const类型'const struct(anonymous struct at ...)'的对象

我已经测试了我能够在https://gcc.godbolt.org/找到的所有GCC和Clang版本.每个版本的GCC都接受代码,而Clang的每个版本都拒绝它.

我想知道在这种情况下哪个编译器是正确的?
标准对此有何看法?

c++ gcc clang language-lawyer constexpr

41
推荐指数
1
解决办法
1659
查看次数

std::less 是否应该允许在编译时比较不相关的指针?

考虑这个代码:

#include <functional>
#include <typeinfo>

template <typename T>
inline constexpr const void *foo = &typeid(T);

int main()
{
    constexpr bool a = std::less<const void*>{}(foo<int>, foo<float>);
} 
Run Code Online (Sandbox Code Playgroud)

Run on gcc.gotbolt.org

如果我使用<而不是std::less这里,代码不会编译。这并不奇怪,因为如果指针指向不相关的对象,则关系指针比较的结果是未指定的,而且显然这样的比较不能在编译时完成。

#include <functional>
#include <typeinfo>

template <typename T>
inline constexpr const void *foo = &typeid(T);

int main()
{
    constexpr bool a = std::less<const void*>{}(foo<int>, foo<float>);
} 
Run Code Online (Sandbox Code Playgroud)

即使我使用std::less. 编译器错误是一样的。std::less似乎<至少在 libstdc++ 和 libc++ 中实现;我在 GCC、Clang 和 MSVC 上得到了相同的结果。

但是,关于 cppreference 的页面 …

c++ std compile-time language-lawyer

39
推荐指数
2
解决办法
1095
查看次数

枚举类的运算符的实现

在讨论了"枚举类"的增量和减量之后,我想问一下enum class类型的算术运算符的可能实现.

原始问题的示例:

enum class Colors { Black, Blue, White, END_OF_LIST };

// Special behavior for ++Colors
Colors& operator++( Colors &c ) {
  c = static_cast<Colors>( static_cast<int>(c) + 1 );
  if ( c == Colors::END_OF_LIST )
    c = Colors::Black;
  return c;
}
Run Code Online (Sandbox Code Playgroud)

有没有办法实现算术运算符而不转换为已定义运算符的类型?我想不出任何东西,但是铸造困扰着我.演员通常表示出现了错误,并且必须有充分的理由让他们使用.我希望语言允许在不强制使用特定类型的情况下实现运算符.

2018年12月更新:其中一篇关于C++ 17的论文似乎至少部分地通过允许枚举类变量和基础类型之间的转换来解决这个问题:http://www.open-std.org/jtc1/sc22/wg21/文档/文件/ 2016/p0138r2.pdf

c++ operator-overloading c++11 enum-class

32
推荐指数
2
解决办法
6万
查看次数

当同时存在模板和非模板重载时,“foo.template bar()”应该做什么?

一位同事与我分享了这段代码:

run on gcc.godbolt.org

#include <iostream>

struct A
{
    void foo() {std::cout << "1\n";}
    
    template <typename T = int>
    void foo() {std::cout << "2\n";}
};

int main()
{
    A x;
    x.template foo();
}
Run Code Online (Sandbox Code Playgroud)

GCC prints 1、 Clang prints2和 MSVC 抱怨缺少模板参数。

哪个编译器是正确的?

c++ language-lawyer

30
推荐指数
2
解决办法
1009
查看次数

如何从C++中的函数返回结构?

我试过几个不同的论坛,似乎无法得到一个直接的答案,我怎么能让这个函数返回结构?如果我试着'返回newStudent;' 我收到错误"没有从studentType到studentType的合适的用户定义转换."

// Input function
studentType newStudent()
{   
    struct studentType
    {
        string studentID;
        string firstName;
        string lastName;
        string subjectName;
        string courseGrade;

        int arrayMarks[4];

        double avgMarks;

    } newStudent;

    cout << "\nPlease enter student information:\n";

    cout << "\nFirst Name: ";
    cin >> newStudent.firstName;

    cout << "\nLast Name: ";
    cin >> newStudent.lastName;

    cout << "\nStudent ID: ";
    cin >> newStudent.studentID;

    cout << "\nSubject Name: ";
    cin >> newStudent.subjectName;

    for (int i = 0; i < NO_OF_TEST; i++)
    {   cout << "\nTest " << …
Run Code Online (Sandbox Code Playgroud)

c++ struct structure return function

25
推荐指数
4
解决办法
9万
查看次数

与“(简单)发生在之前”相比,“强烈发生在之前”有何意义?

该标准定义了几个“发生在之前”关系,这些关系将古老的“之前排序”扩展到多个线程:

\n
\n

[intro.races]

\n

11 评估 A简单地发生在评估 B 之前,如果

\n

(11.1) \xe2\x80\x94 A 在 B 之前排序,或者
\n(11.2) \xe2\x80\x94 A 与 B 同步,或者
\n(11.3) \xe2\x80\x94 A 只是发生在 X 之前,并且X 只是发生在 B 之前。

\n

[注10:在没有消耗操作的情况下,发生在之前和简单发生在关系之前是相同的。\xe2\x80\x94 尾注]

\n

12 评估 A强烈发生在评估 D 之前,如果:

\n

(12.1) \xe2\x80\x94 A 在 D 之前排序,或者
\n(12.2) \xe2\x80\x94 A 与 D 同步,并且 A 和 D 都是顺序一致的原子操作\n([atomics.order] ),或
\n(12.3) \xe2\x80\x94 存在评估 B 和 C,使得 A 在 B 之前排序,B 仅发生在 C 之前,并且 C 在 D 之前排序,或者 …

c++ concurrency multithreading language-lawyer c++20

25
推荐指数
1
解决办法
1159
查看次数

为什么我不能在类范围内声明一个概念?

考虑这个代码:

struct A
{
    template <typename T>
    concept foo = true;
};
Run Code Online (Sandbox Code Playgroud)

它不编译。我的 Clang 10 给了我error: concept declarations may only appear in global or namespace scope,GCC 说了类似的话。

有理由不允许吗?我不明白为什么它不能工作,即使封闭类是一个模板。

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

23
推荐指数
1
解决办法
1061
查看次数

当强制 RVO 应用于延长临时生命周期的引用时会发生什么?

当一个引用被另一个延长临时生命周期的引用初始化时,这个新引用不会扩展任何东西。

但是当强制 RVO 阻止引用被复制时会发生什么?

考虑这个例子: run on gcc.godbolt.org

#include <iostream>

struct A
{
    A() {std::cout << "A()\n";}
    A(const A &) = delete;
    A &operator=(const A &) = delete;
    ~A() {std::cout << "~A()\n";}
};

struct B
{
    const A &a;
};

struct C
{
    B b;
};

int main()
{
    [[maybe_unused]] C c{ B{ A{} } };
    std::cout << "---\n";
}
Run Code Online (Sandbox Code Playgroud)

在 GCC 下打印

A()
---
~A()
Run Code Online (Sandbox Code Playgroud)

但在 Clang 下,结果是

A()
~A()
---
Run Code Online (Sandbox Code Playgroud)

哪个编译器是正确的?

乍一看,GCC 做对了。但在这个例子中:

C foo()
{
    return { …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer return-value-optimization

23
推荐指数
1
解决办法
447
查看次数

在类的内部,为什么`auto b() - > decltype(a()){}`有效,但``decltype(a())b(){}`不行?

请考虑以下代码:( Ideone)

struct S
{
    int a() {return 0;}
    decltype(a()) b() {return 1;}
};
Run Code Online (Sandbox Code Playgroud)

它给了我以下错误:

错误:无法在没有对象的情况下调用成员函数'int S :: a()'


另一方面,这段代码很好编译:( Ideone)

struct S
{
    int a() {return 0;}
    auto b() -> decltype(a()) {return 1;}
};
Run Code Online (Sandbox Code Playgroud)


为什么一个例子有效,但另一个例子无法编译?

两个示例中的编译器行为是否完全正确?

如果编译器是正确的,那么为什么标准要求这种奇怪的行为呢?

c++ language-lawyer

21
推荐指数
2
解决办法
524
查看次数

为什么线程清理程序会抱怨获取/释放线程栅栏?

我正在学习不同的记忆顺序。

\n

我有这段代码,它可以工作并通过 GCC 和 Clang 的线程清理程序

\n
#include <atomic>\n#include <iostream>\n#include <future>\n    \nint state = 0;\nstd::atomic_int a = 0;\n\nvoid foo(int from, int to) \n{\n    for (int i = 0; i < 10; i++)\n    {\n        while (a.load(std::memory_order_acquire) != from) {}\n        state++;\n        a.store(to, std::memory_order_release);\n    }\n}\n\nint main()\n{    \n    auto x = std::async(std::launch::async, foo, 0, 1);\n    auto y = std::async(std::launch::async, foo, 1, 0);\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我认为如果它最终没有返回,则“获取”加载是不必要的from,那么“获取”负载是不必要的,因此我决定使用“宽松”负载,然后使用“获取”栅栏。

\n

我期望它能工作,但它被线程清理程序拒绝了,线程清理程序声称并发state++是数据竞争。

\n
#include <atomic>\n#include <iostream>\n#include <future>\n    \nint state = 0;\nstd::atomic_int …
Run Code Online (Sandbox Code Playgroud)

c++ atomic memory-barriers stdatomic thread-sanitizer

21
推荐指数
1
解决办法
1244
查看次数