为什么较新版本的 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 应该是好的。
早期的编译器没有抱怨的原因是他们没有进行一致性检查。
在下文中,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 ofclass 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 failed101 | 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 应该是好的。
早期的编译器没有抱怨的原因是他们没有进行一致性检查。