C 中文周刊 第111期
弄了个qq频道,手机qq点击进入
RSS https://github.com/wanghenshui/cppweeklynews/releases.atom
欢迎投稿,推荐或自荐文章/软件/资源等
请提交 issue
总算放假了
资讯
标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2023-04-26 第199期
gcc 13.1发布,c 23支持丰富了一波 https://gcc.gnu.org/gcc-13/changes.html
不过没有#embed
另外群友LH_mouse的线程库合进去了
https://github.com/gcc-mirror/gcc/commit/f036d759ecee538555fa8c6b11963e4033732463
有想要体验的可以尝试下MCF
文章
- Did you know that C 17 added std::forward_as_tuple and std::make_from_tuple and what’s the difference between them
int main() {
struct foo {
int i;
bool b;
};
const int i = 42;
const auto f = std::make_from_tuple<foo>(std::forward_as_tuple(i, true));
std::cout << f.i << ' ' << f.b << 'n'; // prints 42 1
}
没啥说的
- The obvious final step
有时候写出这种代码就很烦
代码语言:javascript复制xml.begin_element("port");
xml.attribute("name", name);
xml.attribute("location", loc);
xml.end_element("port"); // <-- the obvious final step
还有就是事务那种
代码语言:javascript复制DBTransaction trx{parameters};
trx.execute(sql1);
trx.execute(sql2);
trx.commit(); // <-- the obvious final step
其实很像lock 搞个scope_guard有点大材小用,之前也提到过,对于mutex把它和保护对象合成一个类,然后暴露个with接口,比如
代码语言:javascript复制struct Thing {
MutexProtected<Field> field;
};
thing->field.with([&](Field& field) {
use(field);
});
按照这种思路,上面两段代码可以改成
代码语言:javascript复制template <typename Callback>
void XML::with_element(std::string_view name, Callback userLogic)
{
begin_element(name);
userLogic();
end_element(name);
}
// User code:
xml.with_element("port", [&] {
xml.attribute("name", name);
xml.attribute("location", loc);
});
db_transaction(parameters, [&]{
trx.execute(sql1);
trx.execute(sql2);
};
随着lambda的引入,感觉又不清晰了是不是,但是确实写的干净一些
- Don’t Look UB: Exposing Sanitizer-Eliding Compiler Optimizations
利用sanitizer来矫正优化,修改代码,概念有点意思
代码没开源 https://github.com/vusec/LookUB
- The View of The String
老生常谈,string string_view一些使用问题
- How to check if a pointer is in a range of memory
给你一个指针和一个范围
代码语言:javascript复制byte* regionStart;
size_t regionSize;
if (p >= regionStart && p < regionStart regionSize)
这样检查范围是对的吗?
不一定,看内存分配的设计,有些老系统设计可能会有一些荣誉,比如把32拆两半,前一半表示具体块,后一半表示offset,这种场景下最末端不一定等于regionstart regioinSize,分布方式可能没那么简单
- Why is std::hardware_destructive_interference_size a compile-time constant instead of a run-time value?
没啥说的,这个值是标准库为你准备的常见cacheline值,信不过就自已指定
- Fold Expressions for Metaprogramming or “The Wrong Reason to Rightfully Want Extension Methods in C ”
考虑一个tuple合并场景,我需要tuple转发一组不同类型的参数,如果类型相同就吃掉
第一版
代码语言:javascript复制// Declare the template
template <typename Tuple, typename... Types>
struct TupleSet {};
// Specialize for our case: carry our 'return value'
// in the first template argument, and all the info
// to process in the rest
template <typename Type1, typename... Types, typename... TupleArgs>
struct TupleSet<std::tuple<TupleArgs...>, Type1, Types...> {
using Type = TupleSet<
std::conditional_t<
(std::same_as<TupleArgs, Type1> || ... || false),
// If `Type1` is already in the tuple, don't add it
std::tuple<TupleArgs...>,
// Else append it to the end of the tuple
std::tuple<TupleArgs..., Type1>
>, Types...
>::Type;
};
// Terminating specialization: nothing left to process
template <typename... TupleArgs>
struct TupleSet<std::tuple<TupleArgs...>> {
using Type = std::tuple<TupleArgs...>;
};
template <typename... Types>
usign TupleSetT = typename TupleSet<std::tuple<>, Types...>;
static_assert(std::same_as<TupleSetT<int, float>, std::tuple<int, float>>);
static_assert(std::same_as<TupleSetT<int, float, int>, std::tuple<int, float>>);
//使用
template <std::totally_ordered... Types>
TupleSetT<Types...> f(Types...);
已经有点反应不过来了,这里只是解决了返回值的问题,还没实现f,但是这个实现已经有点复杂了
换种思路实现,重载 operator
代码语言:javascript复制// Overload operator
// Adding a `Type` to `std::tuple` procuces a new tuple
// with `Type` as the last argument if `Type` was not in
// tuple's arguments. The return type is the same as the
// original tuple otherwise
template <typename Type, typename... Types>
std::conditional_t<
(std::same_as<Types, Type> || ... || false),
std::tuple<Types...>, std::tuple<Types..., Type>
> operator (std::tuple<Types...>, Type);
// Note that no definition is provided for this overload
// There's not going to be one: we only need this for type
// deduction and we don't want it to be called from the
// acutual running code.
// Use C 17 fold expressions to bypass writing a recursive template
template<typename... Types>
using TupleSetT = decltype((std::declval<std::tuple<>>() ... std::declval<Types>()));
可能有命名空间冲突问题,这里可以通过加个名字空间来解决
代码语言:javascript复制namespace detail {
template<typename... Types>
using TupleSetT = decltype((std::declval<std::tuple<>>() ... std::declval<Types>()));
}
using detail::TupleSetT;
或者说,不用TupleSet,最终方案长这样
代码语言:javascript复制namespace detail {
template <std::totally_ordered Type, std::totally_ordered... Types>
constexpr auto operator (std::tuple<Types...> tup, Type t) {
if constexpr ((std::same_as<Types, Type> || ... || false)) {
auto& tupVal = std::get<Type>(tup);
if (tupVal < t) tupVal = t;
return tup;
} else {
return std::make_tuple(std::get<Types>(tup)..., t);
}
}
}
template <std::totally_ordered... Types>
constexpr auto f(Types... args) {
using detail::operator ; // Thankfully, available at function-scope
return (std::tuple<>{} ... args);
}
static_assert(f(1, 2, 2.3, 5, 'c', 1.2) == std::make_tuple(5, 2.3, 'c'));
c 23怎么写?
代码语言:javascript复制template <typename T, typename Func>
requires std::invocable<Func, T>
constexpr auto operator>>=(T t, Func func) {
return func(t);
}
constexpr auto f(auto... args) {
constexpr auto op = [] <typename Type> (Type arg) {
return [arg] <typename... Types> (std::tuple<Types...> tup) {
if constexpr ((std::same_as<Types, Type> || ... || false)) {
auto& tupVal = std::get<Type>(tup);
if (tupVal < arg) tupVal = arg;
return tup;
} else {
return std::make_tuple(std::get<Types>(tup)..., arg);
}
};
};
return (std::tuple<>{} >>= ... >>= op(args));
}
static_assert(f(1, 2, 2.3, 5, 'c', 1.2) == std::make_tuple(5, 2.3, 'c'));
上面的代码我一行都看不懂
- Vectorized trimming of line comments toml文件长这样
[build-system] # use this to indicate the name of the project
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[tool.setuptools]
package-dir = {"" = "pylib"}
packages = ["gyp", "gyp.generator"] # looks good
# end of the file
如何高效的没有if循环,干掉#?
看代码
代码语言:javascript复制bool overflow = 1;
for (size_t i = 0; i < b.line_end.size(); i ) {
// We subtract b.line_end from b.hash, with overflow handling.
overflow = __builtin_usubll_overflow(b.hash[i],
b.line_end[i] overflow,
&b.comment[i]);
b.comment[i] &=~b.hash[i]; // when there is more than one #,
//we want to remove it.
b.comment[i] |= b.line_end[i]; // we want to keep the line start bits.
}
开源项目需要人手
- asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
- Unilang deepin的一个通用编程语言,点子有点意思,也缺人,感兴趣的可以github讨论区或者deepin论坛看一看。这里也挂着长期推荐了
- paozhu 国人开发的web库,和drogon联系过没共建而考虑自己的需求基于asio开发。感兴趣的可以体验一下,挂在这里长期推荐了
新项目介绍/版本更新
- BppTree一个b树实现
- fixed-containers