为什么较新版本的 g++ 说 `static_assert(is_trivial_v<_CharT> && is_standard_layout_v<_CharT>);` 而 class 没有改变?

Why is newer version of g++ saying `static_assert(is_trivial_v<_CharT> && is_standard_layout_v<_CharT>);` when class did not change?

在下文中,my_char class 被认为是不平凡的。我在想也许是编译器出了问题,但也许你比我更清楚哪里出了问题。

In file included from /usr/include/c++/11/bits/basic_string.h:48,
from /usr/include/c++/11/string:55,
from /usr/include/c++/11/bits/locale_classes.h:40,
from /usr/include/c++/11/bits/ios_base.h:41,
from /usr/include/c++/11/ios:42,
from /usr/include/c++/11/ostream:38,
from /usr/include/c++/11/iostream:39,
from /home/alexis/my_char.cpp:2:
/usr/include/c++/11/string_view: In instantiation of class std::basic_string_view<main()::my_char, std::char_traits<main()::my_char> >:
/home/alexis/my_char.cpp:24:20: required from here
/usr/include/c++/11/string_view:101:21: error: static assertion failed

 101 |       static_assert(is_trivial_v<_CharT> && is_standard_layout_v<_CharT>);  
     |                     ^~~~~~~~~~~~~~~~~~~~  

/usr/include/c++/11/string_view:101:21: note: std::is_trivial_v<main()::my_char> evaluates to false

这是可编译的代码my_char.cpp:

#include    <iostream>

struct my_char
{
    typedef std::basic_string<my_char>  string_t;

    bool is_null() const
    {
        return f_char == CHAR_NULL;
    }                       

    static my_char::string_t to_character_string(std::string const & s)
    {
        my_char::string_t result;

        for(auto const & ch : s)
        {
            my_char c;
            c.f_char = ch;
            result += c;
        }

        return result;
    }

    char32_t            f_char = CHAR_NULL;
    std::uint32_t       f_line = 0;
    std::uint32_t       f_column = 0;
};

int main()
{
    constexpr char32_t CHAR_NULL = '[=15=]';

    my_char::string_t str;

    my_char c{ 'c' };
    str += c;

    std::cerr << "char = [" << static_cast<char>(str[0].f_char) << "]\n";

    return 0;
}

g++ 版本:g++ (Ubuntu 11.2.0-7ubuntu2) 11.2.0

用于编译以上内容的命令行:

g++ -Wall my_char.cpp

当我删除 to_character_string() 静态函数时,它起作用了。如果我在 class 之外定义该函数,那将无济于事。仍然不是微不足道的。

另一方面,is_null() 函数没有问题。

为什么那个函数会使 class 变得不平凡?

请注意,此 class 在 Ubuntu 18.04 下工作。重要问题出现在 Ubuntu 21.10。我想要么是新支票,要么是旧支票随它去吧。

对于完整的 class 感兴趣的人,可以找到 here.

您的 class my_char 不适合作为 basic_string 的字符类型。来自 cpp-reference:

The class template basic_string stores and manipulates sequences of char-like objects, which are non-array objects of trivial standard-layout type.

如果您遵循琐碎的定义,我们还有其他要求 trivial default constructor:

T has no non-static members with default initializers. (since C++11)

如果您从 class 成员中删除默认初始值设定项,您的 class 应该是好的。

早期的编译器没有抱怨的原因是他们没有进行一致性检查。