标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2024-10-16 第276期
十月邮件列表 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/#mailing2024-10
让status更好的move,避免使用误用
一个pr观察 github.com/apache/arrow/pull/44477
起因
if (auto&& status = functionReturningArrowResult().status(); status.ok())
return 0;
return -1;
显然status是调用出现问题,status()返回的不是值而是const Status& ,而函数执行完了,所以这个Status已经析构,UB
这个问题和range for loop中的悬垂引用问题一样。
这里引入了一个解决办法,支持多种status()方法
constexpr const Status& status() const& { return status_; }
Status status() && { return status_; }
status() 支持两种 分别是普通引用和万能引用,及时的把值复制出来
这种场景我以前也介绍过,但是不单单这么简单,这个PR还改动了别的地方
/// Helper method for implementing Status returning functions in terms of semantically
/// equivalent Result returning functions. For example:
///
/// Status GetInt(int *out) { return GetInt().Value(out); }
template <typename U, typename E = typename std::enable_if<
std::is_constructible<U, T>::value>::type>
Status Value(U* out) && {
if (!ok()) {
- return status();
+ return std::move(*this).status();
}
*out = U(MoveValueUnsafe());
return Status::OK();
}
这算是一个挺妙的改动,std::move(*this)强制右值,这样就会调用status() && 从而帮助编译器优化潜在的悬垂场景
这种增加&&方法不是简单的增加一个就完了,还有其余的影响也需要覆盖到。这个PR算是见到一个思路
https://www.youtube.com/watch?v=9f5hd-8suVE&ab_channel=CppNow
觉得 -fsanitize=leak
[1] 需要preload重跑
麻烦,自己写了个基于ebpf的
https://johnnysswlab.com/what-is-faster-vec-emplace_backx-or-vecx/
emplace_back没有向量化优势
https://lemire.me/blog/2024/10/06/iterating-through-matched-characters-in-modern-c-viewsfilter-and-coroutine/
查找,代码
std::string data = load_file_content("data.html");
std::string_view targets = "<&\r\0";
auto start = data.begin();
auto end = data.end();
while (start != end) {
start = std::find_first_of(start, end, targets.begin(),
targets.end());
if (start != end) {
/* you are pointing at start */
}
}
也可以这样写
size_t location = 0;
while ((location = data.find_first_of(targets, location)) !=
std::string::npos) {
// matched character at data[location]
location++;
}
还可以用range
auto matched_characters =
data | std::views::filter([](char c) {
return c == '<' | c == '&' | c == '\r' | c == '\0';
});
for (const char &c : matched_characters) {
/* you hold a reference to a matched character */
};
甚至可以这样写
auto target_finder = [](auto& data,
auto& targets) -> std::generator<const char *> {
auto start = data.begin();
auto end = data.end();
while (start != end) {
start = std::find_first_of(start, end, targets.begin(),
targets.end());
if (start == end) {
co_return;
}
co_yield start;
start++;
}
};
for (auto match : target_finder(data, targets)) {
/* match is a matched character*/
};
性能比较差还是算了
https://blog.demofox.org/2024/10/04/a-two-dimensional-low-discrepancy-shuffle-iterator-random-access-inversion/
https://blog.demofox.org/2024/10/15/scaling-points-in-a-specific-direction/
看不懂,图形学的
https://quuxplusone.github.io/blog/2024/10/07/wqual-class-return-type/
告警太多,干脆忽略,反正没用
https://lemire.me/blog/2024/09/09/replace-stdstring-by-stdstring_view-when-you-can/
view传值更省,const string&潜在拷贝风险/指针不能彻底优化
他的这个例子是tring table vs 巨大array + stringview维护,stringview占优势。代码就不贴了
https://www.modernescpp.com/index.php/reflection-in-c26/
直接贴代码
简单例子
#include <iostream>
#include <cassert>
#include <concepts>
int main() {
constexpr auto r = ^int;
typename[:r:] x = 42; // Same as: int x = 42;
typename[:^char:] c = '*'; // Same as: char c = '*';
static_assert(std::same_as<decltype(x), int>);
static_assert(std::same_as<decltype(c), char>);
assert(x == 42);
assert(c == '*');
}
使用^拿到类型 std::meta::info,使用[: :] 使用类型
一个enum转string例子
#include <iostream>
#include <experimental/meta>
#include <string>
#include <type_traits>
template<typename E>
requires std::is_enum_v<E> // (1)
constexpr std::string enum_to_string(E value) {
std::string result = "<unnamed>";
[:expand(std::meta::enumerators_of(^E)):] >> // (2)
[&]<auto e>{
if (value == [:e:]) {
result = std::meta::identifier_of(e); // (3)
}
};
return result;
}
template <typename E>
requires std::is_enum_v<E>
constexpr std::optional<E> string_to_enum(std::string_view name) {
template for (constexpr auto e : std::meta::enumerators_of(^E)) {
if (name == std::meta::identifier_of(e)) {
return [:e:];
}
}
return std::nullopt;
}
int main() {
enum Color { red, green, blue };
std::cout << "enum_to_string(Color::red): " << enum_to_string(Color::red) << '\n';
}
(2) 不好懂,你就当一种特殊语法好了,执行指定lambda
内置的metafunction非常多 这里就不列出来了,太长了
感知字段
#include <experimental/meta>
#include <iostream>
struct Base {
int i{};
void inc(int& j){ j++; }
};
consteval auto number(int n) {
//return std::meta::nonstatic_data_members_of(^Base)[n];
return std::meta::members_of(^Base)[n];
}
consteval auto named(std::string_view name) {
for (std::meta::info field : std::meta::members_of(^Base)) {
if (std::meta::has_identifier(field) && std::meta::identifier_of(field) == name)
return field;
}
return std::meta::info{};
}
int main() {
Base base;
base.[:number(0):] = 1;
// base.[:member_number(10):] = 1; Error
std::cout << "base.i= " << base.i << '\n';
base.[:number(1):](base.i);
std::cout << "base.i= " << base.i << '\n';
std::cout << '\n';
base.[:named("i"):] = 3;
std::cout << "base.i= " << base.i << '\n';
base.[:named("inc"):](base.i);
std::cout << "base.i= " << base.i << '\n';
}
感知布局
#include <experimental/meta>
#include <iostream>
#include <utility>
#include <vector>
#include <array>
struct member_descriptor
{
std::size_t offset;
std::size_t size;
bool operator==(member_descriptor const&) const = default;
};
// returns std::array<member_descriptor, N> The company's biggest funding.
template <typename S>
consteval auto get_layout() {
constexpr size_t N = []() consteval {
return nonstatic_data_members_of(^S).size();
}();
std::array<member_descriptor, N> layout;
[: expand(nonstatic_data_members_of(^S)) :] >> [&, i=0]<auto e>() mutable {
layout[i] = {.offset=offset_of(e), .size=size_of(e)};
++i;
};
return layout;
}
struct X
{
char a;
int b;
double c;
};
int main() {
std::cout << '\n';
constexpr auto layout = get_layout<X>();
std::cout << "Layout of struct X:\n";
for (const auto& member : layout) {
std::cout << "Offset: " << member.offset << ", Size: " << member.size << '\n';
}
std::cout << '\n';
}
潜力还是非常大的
https://devblogs.microsoft.com/oldnewthing/20241007-00/?p=110345
对于std::wstring tolower toupper不能用,可能得用icu库u_strToUpper / u_strToLower
概念介绍的不错
https://www.cppstories.com/2018/12/fromchars/
新版本功能进化了,支持浮点数,让from_chars_result支持bool更好用
#include <charconv> // from_char, to_char
#include <string>
#include <iostream>
int main() {
const std::string str { "16.78" };
double value = 0;
const auto format = std::chars_format::general;
const auto res = std::from_chars(str.data(),
str.data() + str.size(),
value,
format);
if (res.ec == std::errc()) {
std::cout << "value: " << value
<< ", distance: " << res.ptr - str.data() << '\n';
} else if (res.ec == std::errc::invalid_argument) {
std::cout << "invalid argument!\n";
} else if (res.ec == std::errc::result_out_of_range) {
std::cout << "out of range! res.ptr distance: "
<< res.ptr - str.data() << '\n';
}
}
c++26可以直接 if (res) { ... }
我都一个月没更新了也没人鸟,感觉没有互动好无聊,大家的互动非常重要,点赞+评论过20,下周必更新