Releases: wanghenshui/cppweeklynews
C++ 中文周刊 第81期
从reddit/hackernews/lobsters/meetingcpp/知乎等等摘抄一些c++动态
弄了个qq频道,手机qq点击进入
欢迎投稿,推荐或自荐文章/软件/资源等
可以贴在下一期草稿里 草稿链接
2022 09 23
马上就国庆节了。节前节后这两周大概率没时间更新了。提前祝大家节日快乐。好好休息
资讯
标准委员会动态/ide/编译器信息放在这里
九月讨论汇总 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/#mailing2022-09
polymorphic_allocator<> instead of type-erasure
这个有点意思,众所周知,std::function用malloc,不能指定allocator,挺坑。如果std::function创建多了。malloc倒是成为瓶颈了。坑。
主要是加个 using allocator_type = std::pmr::polymorphic_allocator<>;
function_ref: a type-erased callable reference
这个讨论好久了。
Proxy: A Polymorphic Programming Library
这个也介绍过,是微软搞的类似folly::poly那种用户态的多态实现。
别的没啥说的。修修补补
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-09-21 第168期
另外还有Azure CTO说c++不行了新项目转rust。c++老大说他喜新厌旧。具体大家搜一搜就好了。不贴出来了。有点八卦
问题在这里 https://www.zhihu.com/question/554750609
文章
这个分配器确实不错。差点项目里就用了。后来研究了一下发现checkpoint麻烦就放弃了。这个设计还是很有意思的
介绍防守编程的,_FORTIFY_SOURCE=3新级别,更严格,能抓到buffer overflow
被符号不匹配告警搞烦了
template <typename T>
bool has_repeated_values(const T& container) {
for (int i = 0; i < container.size() - 1; ++i) {
if (container[i] == container[i + 1]) return true;
}
return false;
}
// 修改后
std::vector vec = ...
if (!empty(vec)) {
for (int i = 1; i < ssize(vec); ...) {
...
}
}
内部帮你static_cast
。快谢谢库作者
看看见识见识
介绍各个平台系统api兼容性
介绍msvc告警的。没啥说的
不太懂windows下的汇编表现
看不太懂
视频
介绍cppfront herb大哥整的新活, cpp2。看个乐
这里有个介绍 https://www.zhihu.com/question/536288519/answer/2682665038
介绍range。没啥说的
开源项目需要人手
- asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
- pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线
新项目介绍/版本更新
- lager 一个UI框架,类似redux
工作招聘
哎。虾皮突发变动搞的人心惶惶啊。
看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!
C++ 中文周刊 第80期
从reddit/hackernews/lobsters/meetingcpp知乎等等摘抄一些c++动态
弄了个qq频道,手机qq点击进入
欢迎投稿,推荐或自荐文章/软件/资源等
可以贴在下一期草稿里 草稿链接
2022 0916
资讯
标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 2022-09-14 第167期
cppcon 2022还在进行中。视频放了几个。没看。有参与者说今年不太行。我去年还没怎么看。看视频信息量太低了。得看PPT然后找视频看。最近没啥空。周末有时间可以看看
文章
打印堆栈支持。看代码
#include <stacktrace>
#include <iostream>
int foo() {
std::cout << std::stacktrace::current();
return {};
}
int main() {
return foo();
}
可算支持了
各个编译器Modules支持的状态进展介绍
标准库的std::optional是不支持T&和void的。作者说了下自己可能会用到这个场景,标准库应该加上
之前介绍过。介绍了谷歌浏览器团队在解决指针问题的一些实践。实现了很多,但是有些文档不可见。
也介绍了其他方案的实现,比如这个unowned_ptr
代码难找就没有深入研究。不过讨论还是值得一看的。我后面整理一下
介绍Sanitizer
seastar代码走读
注意co_await的阻塞语义,永远超时导致不能使用
四舍五入等于c的东西。可以看个热闹
各种容器介绍,比如folly::fbvector, boost::small_vector等等。感兴趣的可以看看
写了个工具验证gcc产出的代码对不对,具体就是验证gimple IR。我不太懂。感兴趣可以看看
office团队要用module,这是msvc团队的一些探索
介绍msvc调试的。没用过不了解,有没有懂的给讲讲
代码长这样
struct WidgetTracker : IWidgetChangeNotificationSink
{
/* other stuff not relevant here */
/// IWidgetChangeNotificationSink
STDMETHODIMP OnCurrentWidgetChanged();
private:
WRL::ComPtr<IWidget> m_currentWidget;
std::mutex m_mutex;
};
HRESULT WidgetTracker::OnCurrentWidgetChanged()
{
auto guard = std::lock_guard(m_mutex);
RETURN_IF_FAILED(GetCurrentWidget(&m_currentWidget));
return S_OK;
}
OnCurrentWidgetChanged是个回调,如果m_currentWidget变了就会被调用
问题在于OnCurrentWidgetChanged被调用这个m_mutex锁住的瞬间,m_currentWidget析构,结果又触发一次OnCurrentWidgetChanged,导致死锁
这个问题根源在于锁锁不住comptr,无法避免递归调用。
解决方法也很简单,拷贝一份对象就行了。
HRESULT WidgetTracker::OnCurrentWidgetChanged()
{
WRL::ComPtr<IWidget> widget; // 可能别人在用它
auto guard = std::lock_guard(m_mutex);
RETURN_IF_FAILED(GetCurrentWidget(&widget));
m_currentWidget.Swap(widget);
return S_OK;
}
作者之前讨论过一段类似的代码,用的,shared_ptr, 也有相同的问题
class ThingManager
{
private:
std::mutex things_lock_;
std::vector<std::shared_ptr<Thing>> things_;
public:
void AddThing(std::shared_ptr<Thing> thing)
{
std::lock_guard guard(things_lock_);
things_.push_back(std::move(thing));
}
void RemoveThingById(int32_t id)
{
std::lock_guard guard(things_lock_);
auto it = std::find_if(things_.begin(), things_.end(),
[&](auto&& thing)
{
return thing->id() == id;
});
if (it != things_.end()) {
things_.erase(it);
}
}
};
class SuperThing : Thing
{
private:
ThingManager& manager_;
int32_t helper_id_ = 0;
public:
SuperThing(ThingManager& manager) :
manager_(manager)
{
auto helper = std::make_shared<Thing>();
helper_id_ = helper->id();
manager_.AddThing(helper);
}
~SuperThing()
{
manager_.RemoveThingById(helper_id_);
}
};
void test(ThingManager& manager)
{
auto s = std::make_shared<SuperThing>(manager);
auto id = s->id();
manager.AddThing(s);
s = nullptr; // 1
manager.RemoveThingById(id); // 2
}
问题是相同的,同一个锁被锁两次。如何触发?首先SuperThing会在2 这行真正的析构,1那行只会引用计数-1
RemoveThingById(id)是会锁的,内部触发了SuperThing析构,然后又调用了manager_.RemoveThingById(helper_id_);
,锁了同一个锁
你可能觉得这种代码写的有问题。这是锁和shared_ptr和坑爹析构三个同时引入引发的问题,我遇不到
解决方法也很简单。让这个shared_ptr活着,因为不知道哪个外部调用会用到这个shared_ptr
void RemoveThingById(int32_t id)
{
std::shared_ptr removed_thing; // 求求你活着
{
std::lock_guard guard(things_lock_);
auto it = std::find_if(things_.begin(), things_.end(), ...);
if (it != things_.end()) {
removed_thing = *it;
things_.erase(it);
}
}
}
引用计数指针和锁的问题。这里打个问号。要注意
oldnewthing的博客真精彩,总能遇到各种莫名其妙的bug
标准库提供了新函数来更友好的判断整数大小,不用自己写那些符号转换逻辑了
比如
template <class _Ty1, class _Ty2>
_NODISCARD constexpr bool cmp_equal(const _Ty1 _Left, const _Ty2 _Right) noexcept {
static_assert(_Is_standard_integer<_Ty1> && _Is_standard_integer<_Ty2>,
"The integer comparison functions only "
"accept standard and extended integer types.");
if constexpr (is_signed_v<_Ty1> == is_signed_v<_Ty2>) {
return _Left == _Right;
} else if constexpr (is_signed_v<_Ty2>) {
return _Left == static_cast<make_unsigned_t<_Ty2>>(_Right) && _Right >= 0;
} else {
return static_cast<make_unsigned_t<_Ty1>>(_Left) == _Right && _Left >= 0;
}
}
VPSUBUSB z, x, y
VPMINUB z, x, y
VPCMPEQB w, z, x
我不太懂。不评价
用avx处理字符串中的斜杠,比如my title is \"La vie\"
通常写法
for (...) {
if ((*in == '\\') || (*in == '"')) {
*out++ = '\\';
}
*out++ = *in;
}
sse/avx写法
__m512i solidus = _mm512_set1_epi8('\\');
__m512i quote = _mm512_set1_epi8('"');
for (; in + 32 <= finalin; in += 32) {
__m256i input = _mm256_loadu_si256(in);
__m512i input1 = _mm512_cvtepu8_epi16(input);
__mmask64 is_solidus = _mm512_cmpeq_epi8_mask(input1, solidus);
__mmask64 is_quote = _mm512_cmpeq_epi8_mask(input1, quote);
__mmask64 is_quote_or_solidus = _kor_mask64(is_solidus, is_quote);
__mmask64 to_keep = _kor_mask64(is_quote_or_solidus, 0xaaaaaaaaaaaaaaaa);
__m512i shifted_input1 = _mm512_bslli_epi128(input1, 1);
__m512i escaped =
_mm512_mask_blend_epi8(is_quote_or_solidus, shifted_input1, solidus);
_mm512_mask_compressstoreu_epi8(out, to_keep, escaped);
out += _mm_popcnt_u64(_cvtmask64_u64(to_keep));
}
给我看困了
这段代码有bug,不懂这几个API的可能看不懂
bool ShuttingDown = false;
void MainThread()
{
DWORD id;
auto hThread = CreateThread(nullptr, 0, WorkerThread,
nullptr, 0, &id); // succeeds
BlahBlahBlah(); // do useful work
// Time to clean up. Post an APC to the worker thread
// to tell it that it's time to go home.
QueueUserAPC(WakeWorker, hThread, 0); // succeeds
WaitForSingleObject(hThread, INFINITE); // hangs
CloseHandle(hThread);
}
void CALLBACK WakeWorker(ULONG_PTR)
{
ShuttingDown = true;
}
DWORD CALLBACK WorkerThread(void*)
{
// Do work until shut down.
do
{
// All work is posted via APCs.
SleepEx(INFINITE, TRUE);
} while (!ShuttingDown);
return 0;
}
简单来说SleepEx通过QueueUserAPC来唤醒,有一种场景,QueueUserAPC唤醒了,但是CreateThread执行的慢,导致SleepEx没收到通知,从而永远死锁
怎么解决这个问题?把do while循环改成while就行了。因为这种场景已经shutdown了,不应该执行sleep
DWORD CALLBACK WorkerThread(void*)
{
// Do work until shut down.
while (!ShuttingDown)
{
// All work is posted via APCs.
SleepEx(INFINITE, TRUE);
}
return 0;
}
- Serializing asynchronous operations in C++/WinRT
- Creating a manual-start C++/WinRT coroutine from an eager-start one, part 1
- Creating a lazy-start C++/WinRT coroutine from an eager-start one, part 2
讲协程的。说来惭愧我还不是很懂。就不介绍了
视频
- [C++ Weekly - E...
C++ 中文周刊 第79期
从reddit/hackernews/lobsters/purecpp知乎等等摘抄一些c++动态
弄了个qq频道,手机qq点击进入
欢迎投稿,推荐或自荐文章/软件/资源等
可以贴在下一期草稿里 草稿链接
2022 0908 提前发了。周五有事
资讯
标准委员会动态/ide/编译器信息放在这里
llvm 15发布了。c++20支持等等一大堆修改
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-09-07 第166期
文章
-
最新全面hashmap 评,其中emhash7/8 是知乎网友ktrpime 实现的的,性能排名还不错。感兴趣的可以研究下
要注意协程被线程切换影响
c++23详细总结
c++20应用协程举例
std::function的分析
seastar的一些代码走读。可以看看
其实就是编译期检测接口的能力
一组协程教程
#include <ranges>
template <auto Begin, auto End, auto List>
auto slice = List
| std::ranges::views::drop(Begin)
| std::ranges::views::take(End);
static_assert(
slice<1_c, 2_c, boost::mp::list<int, double, float>()>
==
boost::mp::list<double, float>());
typelist实现更简单了。恐怖
optinal的move并不会真正的move T, 让T为无效value
template <typename T>
void test(T v)
{
optional<T> o = v;
assert (o); // o contains a value
optional<T> p = std::move(o);
assert (o); // o still contains a value!
}
完全取决于T的move,optional会保留T的壳子。
比如unique_ptr
int * p = new int(1);
optional<unique_ptr<int>> op = unique_ptr<int>(p);
assert (op);
assert (op->get() == p);
optional<unique_ptr<int>> o2 = std::move(op);
assert (op); // still contains a value
assert (op->get() == nullptr); // the value is moved from
assert (o2);
assert (o2->get() == p);
unique_ptr内部会搬走,但本身是还在optional里的。这样实现更快,对于trival类型,这样优化的可以直接memcpy,更高效一些
大概实现成这个样子
template <typename Trivial>
class optional<Trivial>
{
bool _is_initialized;
Trivial _value;
optional() : _is_initialized(false) {}
// use defaulted copy and move
};
// Second argument is a pointer to the type of std::fclose, we could also have
// written it out explicitly as std::unique_ptr<FILE, int (*)(FILE*)>.
using FilePtr = std::unique_ptr<FILE, decltype(std::fclose) *>;
// Instantiate the FILE* with the destructor we want.
FilePtr file(std::fopen(filename, "rbe"), std::fclose);
// Do stuff with the file
std::fread(buf_.data(), 1, buf_.size(), file.get());
比写个deferGuard能更干净些
using XXH3StatePtr = std::unique_ptr<XXH3_state_t, decltype(XX3_freeState) *>;
XXH3StatePtr state(XXH3_createState(), XXh3_freeState);
但这种写法的问题在于,需要判定创建失败/指针是否有效
一个简单的函数
[[nodiscard]] auto say_a_to(
std::string_view what, std::string_view name) -> std::string {
return std::string{what} + ", " + std::string{name} + "!";
}
say_a_to("Hi", "Kate"); // -> "Hi, Kate!"
struct {
[[nodiscard]] auto operator()(
std::string_view what, std::string_view name) const -> std::string {
return std::string{what} + ", " + std::string{name} + "!";
}
} say_b_to;
say_b_to("Hello", "Tony"); // -> "Hello, Tony!"
没啥新奇的,但是c++23支持多维数组了,所以说operator[]
也算是一种函数了
比如
struct {
[[nodiscard]] auto operator[](
std::string_view what, std::string_view name) const -> std::string {
return std::string{what} + ", " + std::string{name} + "!";
}
} say_d_to;
say_d_to["Goodbye", "Tony"]; // -> "Goodbye, Tony!"
struct {
template <std::integral ...Ts>
[[nodiscard]] auto operator[](Ts... ts) const noexcept {
return (0 + ... + ts);
}
} sum;
const auto s1 = sum[1, 2, 3]; // 6
const auto s2 = sum[]; // 0
我只能说看个乐,别这么写求求了
视频
#include <iostream>
#include <ranges>
#include <string_view>
int main() {
// this is lazily evaluated
auto strings = std::string_view{"Hello C++ 20"} | std::views::split(' ');
// the result is a range of ranges
for (const auto &ref : strings) {
// C++ 20
std::cout << '\n' << std::string_view{ref.begin(), ref.end()};
// C++ 23
std::cout << '\n' << std::string_view{ref};
}
}
开源项目需要人手
- asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
- pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线
工作招聘
寒冬了
华为出新手机了,但我不买,因为想把寒冬传给它
看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!
C++ 中文周刊 第78期
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态
弄了个qq频道,手机qq点击进入
欢迎投稿,推荐或自荐文章/软件/资源等
可以贴在下一期草稿里 草稿链接
2020 09 02
资讯
标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-08-31 第165期
文章
尽量让move 构造函数 noexcept, 不然用vector可能有问题,多copy
比如这个
struct Instrument {
int n_;
std::string s_;
Instrument(const Instrument&) = default;
// WRONG!!
Instrument(Instrument&& rhs)
: n_(std::exchange(rhs.n_, 0)),
s_(std::move(s_))
{}
// RIGHT!!
Instrument(Instrument&& rhs) noexcept
: n_(std::exchange(rhs.n_, 0)),
s_(std::move(s_))
{}
};
如果不是noexcept,vector的move判定内部的T不是is_nothrow_move_constructible, 那就构造复制一份,所以多了个拷贝。也就是博主说的vector pessimization问题
vector本身的搬迁move的多余动作,如果能nothrow,move就更简单
free没有size看上去是个巧妙的设计,实际上隐含了挺多脏活
协程背后都做了啥
有点意思
struct foo {
[[nodiscard]] foo(auto& resource) {}
};
struct [[nodiscard]] bar {};
auto fn() -> bar;
[[nodiscard]] auto fn2() -> bool;
int main(int, char** argv){
foo{argv}; // ignoring temp created by [[nodiscard]]
fn(); // ignoring return value with [[nodiscard]]
fn2(); // ignoring return value with [[nodiscard]]
}
老文,科普一下概念。
参数不是constexpr
consteval auto square(int x) -> int { return x * x; }
constexpr auto twice_square(int x) -> int { return square(x); }
编译不过。作者展示了一下编译期计算。哎又回去了。constexpr还是不够const
看个乐
介绍这几个flag
-march=native
肯定接触过吧
茴香豆的茴的20种写法
为什么大哥解bug这么熟练
视频
static constexpr 和 inline constexpr区别。inline constexpr能合并文件重复的数据,是文件级别,static是函数级别,并不能合并代码段
聪明的你想到了static inline constexpr。这个效果就是static constexpr。static限制了范围
开源项目需要人手
- asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
- pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线
工作招聘
寒冬了
看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!
C++ 中文周刊 第77期
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态
弄了个qq频道,手机qq点击进入
欢迎投稿,推荐或自荐文章/软件/资源等
可以贴在下一期草稿里 链接
2022 08 26
准备做视频,目前有代码走读/benchmark俩主题,大家还有啥意见可以供稿一下。下一期视频准备先来个userver代码走读。我先准备准备材料
资讯
标准委员会动态/ide/编译器信息放在这里
标准委员会八月邮件 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/#mailing2022-08
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-08-24 第164期
文章
namespace detail {
template <bool> struct conditional;
template <> struct conditional<false> {
template <class, class T> using fn = T;
};
template <> struct conditional<true> {
template <class T, class> using fn = T;
};
} // namespace detail
template <bool B, typename T, typename F>
using conditional_t = typename detail::conditional<B>::template fn<T, F>;
说实话,没看懂
关于协程的封装探索,挺有意思的
看不懂
GCC整体介绍
看个乐
fmt对输出有严格限制
介绍他自己写的静态检查器 https://github.com/GregUtas/robust-services-core
main函数执行前都干了啥,填充入参之类的
#include <iostream>
#include <string>
#include <stdlib.h>
std::string message;
extern "C" {
void __asan_on_error() {
std::cout << "You caused an error: " << message << std::endl;
}
}
int main() {
int array[8];
for(int k = 0;; k++) {
message = std::string("access at ") + std::to_string(k);
array[k] = 0;
}
return EXIT_SUCCESS;
}
不过不太实用
memcmp比较出错。qemu这种牛逼软件也会有这种问题啊
int arr[10000]; // 一个已有的数组
mdspan mdarr{arr, i, j, k}; // 把已有的数组 arr 视作 i×j×k 的多维数组
int value = mdarr[x, y, z]; // 访问多维数组的元素
mdarr[x, y, z] = 42; // 向元素赋值
简而言之就是这几行。现在你已经学会了
视频
-ftime-trace 生成编译的时间json结果,可以用chrome://tracing/ 浏览器来加载查看。可以自己试一试
觉得麻烦想快速验证的,这里有个build bench https://build-bench.com/b/zLopSp4Yj5XaijZSuwqiYvA2PNU
开源项目需要人手
- asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
- pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线
新项目介绍/版本更新
- cake 一个c写的c前端
- asyncgi 一个fastcgi库
- MultiArena 内存分配器实现,O1,定位类似pmr
工作招聘
突然寒冬卧槽了,任正非你这嘴开过光吧
看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!
C++ 中文周刊 第76期
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态
弄了个qq频道,手机qq点击进入
欢迎投稿,推荐或自荐文章/软件/资源等
可以贴在下一期草稿里 https://github.com/wanghenshui/cppweeklynews/blob/dev/posts/077.md
2022 08 19
解不出bug要被开了。有没有工作岗位推荐的
资讯
标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-08-17 第163期
文章
类似folly::Poly
std::expected<std::vector<int>, Status> ReadData()
{
if (!HasAcccess())
return std::unexpected<Status> { Status::AccessDenied };
if (OpenConnection() != 0)
return std::unexpected<Status> {Status::DataSourceError};
if (Fetch() != 0)
return std::unexpected<Status> {Status::DataError};
std::vector<int> data;
data.push_back(42);
return data;
}
相当于StatusWith<T>
这种组件
void report_error();
[[gnu::cold]] void report_error_cold();
void logic();
/*
cold(bool):
test edi, edi
jne .LBB0_1
jmp logic()
.LBB0_1:
jmp report_error_cold()
*/
auto cold(bool error) {
if (error) {
report_error_cold();
return;
}
logic();
}
/*
normal(bool):
test edi, edi
je .LBB1_2
jmp report_error()
.LBB1_2:
jmp logic()
*/
auto normal(bool error) {
if (error) {
report_error();
return;
}
logic();
}
/*
unlikely(bool):
test edi, edi
jne .LBB2_1
jmp logic()
.LBB2_1:
jmp report_error()
*/
auto unlikely(bool error) {
if (error) [[unlikely]] {
report_error();
return;
}
logic();
}
对代码优化有点帮助。之前也介绍过
对比了一下各种atomic 锁之类的差异
看个乐
这个优化了解一下
视频
// #embed 支持
//#embed </path/to/file.txt>
//constexpr 部分支持
// not allowed in c23 :(
//constexpr int get_value() {
// return 42;
//}
// allowed in c23!
constexpr int universe_and_everything = 42;
// [[attributes]]支持
[[nodiscard]] int get_value();
// deprecated, fallthrough, maybe_unused, nodiscard, noreturn
// 未命名参数
int do_work(int x, int)
{
return x * 23;
}
// 类型枚举
enum MyEnum : char {
x,
y
};
// #6 __has_include
#if __has_include("somefile")
#include("somefile");
#endif
开源项目需要人手
- asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
- pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线
新项目介绍/版本更新
- bloaty 查看代码的膨胀程度
- passgen 根据指定正则生成密码
- async_simple 协程库,阿里的,有demo。不过是部分开源
- natalie c++写的ruby
- jank c++写的Clojure
工作招聘
解不出bug要被开了
看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!
C++ 中文周刊 第74期 && 75期
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态
弄了个qq频道,手机qq点击进入
欢迎投稿,推荐或自荐文章/软件/资源等,请提交 issue
74忘记发了。74 75 合着发吧
资讯
标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-08-03 第161期
文章
c++的bind和网络库的bind符号冲突了。很搞笑。不过在linux环境下没有这个问题
我之前在windows平台遇到过log日志接口和cmath的log函数有符号冲突。msvc这个方面做的不是很好
/*
divide_by_32_no_assume(int):
lea eax, [rdi + 31]
test edi, edi
cmovns eax, edi
sar eax, 5
ret
*/
auto divide_by_32_no_assume(int x) {
return x / 32;
}
/*
divide_by_32_assume(int):
mov eax, edi
shr eax, 5
ret
*/
auto divide_by_32_assume(int x) {
__builtin_assume(x >= 0);
return x / 32;
}
这个之前提到过,有个经典的fast-math开关优化。那个力度比较大。这里你可以自主控制,力度更精细一些
同一个代码段 c和c++有很大区别。主要是逗号表达式,左值右值,位域,类型转换,类型大小,空类型,匿名结构体等等。感兴趣的可以看看。
介绍TSAN的原理
介绍内核内存分配策略
用c++实现structopt, 看个乐
没看明白
一个bug
template<class It>
bool is_palindrome(It first, It last) {
while (first != last) {
--last;
if (first == last) break;
if (*first != *last) {
return false;
}
++first;
}
return true;
}
很自然的,可以改写成
template<class It>
bool is_palindrome(It first, It last) {
return std::equal(
first, last,
std::reverse_iterator(last),
std::reverse_iterator(first)
);
}
这里没用make_reverse_iterator,用的CTAD自动推导。但是这个推导可能不是我们预想的那样
std::string s = "foo";
assert(!is_palindrome(s.begin(), s.end()));
assert(is_palindrome(s.begin()+1, s.end()));
assert(!is_palindrome(s.rbegin(), s.rend()));
assert(is_palindrome(s.rbegin(), s.rend()-1)); // Fails! Oof!
最后两个例子,已经是reverse的iterator, CTAD什么都不做,而不是推导成 reverse_iterator<iterator>
这种东西,所以报错了
尽量别用CTAD。降低入门门槛但是引入了背景,不熟就掉坑
基础知识。值得看看
static_assert(typeid([]{}) != typeid([]{}));
template<auto = []{}>
struct foo{};
foo f1, f2;
static_assert(typeid(f1) != typeid(f2));
没什么卵用的知识,也是一个坑
利用concept和constexpr代替enable if 代码不列举了
int main()
{
constexpr auto factorial23 = [](this auto&& self, int n) {
if (n <= 1)
return 1;
return n * self(n - 1);
};
static_assert(factorial23(5) == 120);
}
递归+编译期 lambda,玩的花
分析bug挺有意思
老生常谈了,可读性问题,别用bool做多个参数,不然分不清啥是啥
简单压测,QT的信号槽比虚函数观察者模式并不快。看个乐
仓库在这里https://github.com/rnburn/rules_cc_module
总算支持了
一个课程,可以看看
值得一看,拓展思路
又是SIMD。可以看看
gdb调试。值得一看
视频
代码在这里https://compiler-explorer.com/z/nbGGdMM4b
开源项目需要人手
- asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
- pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线
新项目介绍/版本更新
- userver yandex微服务框架。轻松拼凑出可用微服务,内置http/grpc
- hspp Haskell Style Programming brought to C++ 不懂haskell 不评价
- flecs 又一个ECS框架
- YACLib Yet Another Concurrency Library
- HPX 1.8.1 Released
- Using Landlock to Sandbox GNU Make
- hscpp: A library to hot-reload C++ at runtime
- static_functional
- Compile time finite state machine 编译期状态机
- boost 1.80.0 没有新库,一堆bugfix
- boost.url 一个URL库
- 手把手写c编译器
- 一个c++20 rpc框架
工作招聘
看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!
C++ 中文周刊 第73期
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态
弄了个qq频道,手机qq点击进入
欢迎投稿,推荐或自荐文章/软件/资源等,请提交 issue
2022 07 29
资讯
标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-07-27 第160期
文章
手把手教你写错误处理的代码
值得一看
使用folly遇到的问题以及解决。看个乐
了解一下
概念复习
概念复习
压测代码在这里https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/tree/master/2020/09/10
速度对比 strtod 270 MB/s from_chars 1 GB/s 用哪个不用我多说了吧
windows我不懂,不过还可以这么操作的??
开源项目需要人手
- asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
- pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线
新项目介绍/版本更新
- STL MSVC STL组老大自己实现的刚进c++23的import std; 感谢@c8ef 投稿
- lazyfs 一个fake fs实现
- listdb 论文开源代码。基于pmem,生成比直接用pmdk的rocksdb快 今天突然得知pmem 被英特尔砍了。悲
- jsonpp 一个json库
工作招聘
有没有需要看大门的
看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!
C++ 中文周刊 第72期
从reddit/hackernews/lobsters/摘抄一些c++动态
弄了个qq频道,手机qq点击进入
欢迎投稿,推荐或自荐文章/软件/资源等,请提交 issue
2022 0726 最近有点忙
资讯
标准委员会动态/ide/编译器信息放在这里
七月邮件汇总
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-07-20 第159期
文章
讲完美哈希表的。这个知识好像没怎么普及开,这里推荐一下
一个思路,禁止各种make,只能从静态函数构造
template<typename T>
struct require_make_shared :
public std::enable_shared_from_this<T>
{
protected:
struct use_the_create_method {
explicit use_the_create_method() = default;
};
public:
template<typename...Args>
static auto create(Args&&... args)
{
return std::make_shared<T>
(use_the_create_method{},
std::forward<Args>(args)...);
}
// Deny copy construction
require_make_shared(require_make_shared const&) = delete;
};
class Widget : public require_make_shared<Widget>
{
public:
Widget(use_the_create_method);
Widget(use_the_create_method, int);
Widget(use_the_create_method, int, int);
};
void test()
{
auto v1 = Widget::create(); // okay
auto v2 = std::make_shared<Widget>(); // nope
auto v3 = std::make_unique<Widget>(); // nope
Widget v4; // nope
}
std::string s{"there is a needle in the haystack"};
std::string_view sv{"acdef"};
if (s.contains("needle")) { // 总算有这个api了
std::cout << "we found a needle in: " << std::quoted(s) << '\n';
}
if (!sv.contains('b')) {
std::cout << "we did not find a 'b' in: " << std::quoted(sv) << '\n';
}
std::string s(nullptr); //不会挂了
basic_string::resize_and_overwrite() 可以省一个写,用不上的可以先用gcc内置函数
std::string s { "Food: " };
s.resize_and_overwrite(10, [](char* buf, int n) {
return std::find(buf, buf + n, ':') - buf;
});
std::cout << "2. " << std::quoted(s) << '\n';
c23支持embed了,c++23还不支持std::embed。服了
介绍一下embed,看代码你就懂了
#include <assert.h>
int main (int, char*[]) {
static const char sound_signature[] = {
#embed <sdk/jump.wav>
};
static_assert((sizeof(sound_signature) / sizeof(*sound_signature)) >= 4,
"There should be at least 4 elements in this array.");
// verify PCM WAV resource signature (at run-time)
assert(sound_signature[0] == 'R');
assert(sound_signature[1] == 'I');
assert(sound_signature[2] == 'F');
assert(sound_signature[3] == 'F');
return 0;
}
定制formatter,代码不贴了
auto foo(auto&&);
int main() {
int i{};
const int c{};
foo(42); // int
foo(i); // int&
foo(int{i}); // int
foo(auto{i}); // int
foo(auto(42)); // int
foo(c); // const int&
foo(int{c}); // int
foo(auto(c)); // int
}
这个也讲过很多次了。有些场景是需要copy语义的,否则莫名其妙出现了改动,解决办法就是让他退化,拿到copy
这个例子也说过很多次了
#include <iostream>
template<class T>
constexpr std::decay_t<T>
decay_copy(T&& v)
noexcept(std::is_nothrow_convertible_v<T, std::decay_t<T>>) // exposition only
{
return std::forward<T>(v);
}
int main() {
std::vector<int> v1{1, 2, 1, 1, 1};
auto v2 = v1;
v1.erase(
std::remove(begin(v1), end(v1), *std::max_element(begin(v1), end(v1))),
v1.end());
v2.erase(std::remove(
begin(v2), end(v2),
decay_copy(*std::max_element(begin(v2), end(v2)))),
v2.end());
std::cout << "v1.size()=" << v1.size() << std::endl
<< "v2.size()=" << v2.size()
<< std::endl;
return 0;
}
p2162继承variant各个编译器已经支持了。作者展示了一种优雅的用法
#include <cstdint>
#include <iostream>
using namespace std;
struct Request {
static constexpr uint8_t id_num {1};
uint8_t req_val;
void encode(ostream& os) const {
os.put(req_val);
}
void decode(istream& is) {
req_val = is.get();
}
};
struct Affirmative {
static constexpr uint8_t id_num {2};
uint8_t resp_val;
void encode(ostream& os) const {
os.put(resp_val);
}
void decode(istream& is) {
resp_val = is.get();
}
};
struct Failure {
static constexpr uint8_t id_num {3};
uint8_t resp_val;
void encode(ostream& os) const {
os.put(resp_val);
}
void decode(istream& is) {
resp_val = is.get();
}
};
#include <variant>
#include <exception>
struct Packet : variant<Request, Affirmative, Failure> {
using variant::variant;
Packet(uint8_t id) : variant {from_id(id)} {}
Packet(istream& is) {
decode(is);
}
void encode(ostream& os) const {
visit([&](const auto& inner){
os.put(inner.id_num);
inner.encode(os);
}, *this);
}
void decode(istream& is) {
*this = from_id(is.get());
visit([&](auto& inner){ inner.decode(is); }, *this);
}
private:
static Packet from_id(uint8_t id) {
switch(id) {
case Request::id_num:
return Request {};
case Affirmative::id_num:
return Affirmative {};
case Failure::id_num:
return Failure {};
}
throw std::runtime_error {"Invalid Packet Id!"};
}
};
#include <concepts>
#include <sstream>
#include <fmt/format.h>
using fmt::print;
int main(void) {
Packet p {Request {.req_val {5}}};
stringstream buf;
p.encode(buf);
Packet decoded {buf};
visit([](const auto& inner){
using T = decltype(auto(inner));
if constexpr(same_as<T, Request>)
print("I am a Request with a val of: {}", inner.req_val);
else if constexpr(same_as<T, Affirmative>)
print("I am an Affirmative with a val of: {}", inner.resp_val);
else if constexpr(same_as<T, Failure>)
print("I am a Failure with a val of: {}", inner.resp_val);
}, decoded);
}
这种写法确实挺爽的,有点猥琐的模式匹配那个味了,https://godbolt.org/z/rqYeY5r1f
作者也展示了用concept达到类似的效果
#include <concepts>
struct Stranger {};
using Person = variant<Alice, Bob, Stranger>;
template <typename T>
concept IsNamed = requires(T p) {
{ p.name() } -> convertible_to<string_view>;
};
void print_name(Person& p) {
visit([](auto& inner) {
if constexpr(IsNamed<decltype(inner)>)
print("Name: {}\n", inner.name());
else
print("This is a stranger!\n");
}, p);
}
也不是不行,就是concept一般人比较不好接受
讲裁剪二进制的。
视频
通过函数make_lambda返回一个lambda,然后推导这个lambda的类型,就可以放到vector里了。直接用lambda不行,类型信息是匿名的,无法使用。
或者用std::function不就行了?
开源项目需要人手
- asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
- pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线
新项目介绍/版本更新
说实话格局低了。自己开新坑不如隔壁meta推出新IR修缮
另外下一个c++不是rust么,都这么多年了,为啥会选你carbon,除非像go一样硬推
- indirect_value pimpl惯用法的另一种实现, 可以看这个设计https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1950r1.html 挺有意思的
- BTree 一个可罗盘的btree实现。看个乐
工作招聘
有没有需要招扫地僧式保洁的。我会拖地
看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!
C++ 中文周刊 第71
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态
弄了个qq频道,手机qq点击进入
欢迎投稿,推荐或自荐文章/软件/资源等,请提交 issue
2022 07 15
资讯
CPPcon 2022要开始了。2021我还没有看完
标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2022-07-13 第158期
文章
值得一看
值得一看
了解一下asio的背景
上面这四篇都是purecpp公众号的。大家也可以去公众号看看
感兴趣的看下吧。数学和图形学?看不懂
- Processing a ValueSet or PropertySet even in the face of possible mutation, part 1
- Processing a ValueSet or PropertySet even in the face of possible mutation, part 2
- Processing a ValueSet or PropertySet even in the face of possible mutation, part 3
手把手教你写代码,考虑各种场景
介绍msvc特性
arm的特性。现在arm的机器越来越多了。省钱
代码长这样。有兴趣的可以看看,我看不懂
void remove_negatives(const int32_t *input, int64_t count, int32_t *output) {
int64_t j = 0;
const int32_t* endPtr = input + count;
const uint64_t vl_u32 = svcntw();
svbool_t all_mask = svptrue_b32();
while(input <= endPtr - (4*vl_u32))
{
svint32_t in0 = svld1_s32(all_mask, input + 0*vl_u32);
svint32_t in1 = svld1_s32(all_mask, input + 1*vl_u32);
svint32_t in2 = svld1_s32(all_mask, input + 2*vl_u32);
svint32_t in3 = svld1_s32(all_mask, input + 3*vl_u32);
svbool_t pos0 = svcmpge_n_s32(all_mask, in0, 0);
svbool_t pos1 = svcmpge_n_s32(all_mask, in1, 0);
svbool_t pos2 = svcmpge_n_s32(all_mask, in2, 0);
svbool_t pos3 = svcmpge_n_s32(all_mask, in3, 0);
in0 = svcompact_s32(pos0, in0);
in1 = svcompact_s32(pos1, in1);
in2 = svcompact_s32(pos2, in2);
in3 = svcompact_s32(pos3, in3);
svst1_s32(all_mask, output + j, in0);
j += svcntp_b32(all_mask, pos0);
svst1_s32(all_mask, output + j, in1);
j += svcntp_b32(all_mask, pos1);
svst1_s32(all_mask, output + j, in2);
j += svcntp_b32(all_mask, pos2);
svst1_s32(all_mask, output + j, in3);
j += svcntp_b32(all_mask, pos3);
input += 4*vl_u32;
}
int64_t i = 0;
count = endPtr - input;
svbool_t while_mask = svwhilelt_b32(i, count);
do {
svint32_t in = svld1_s32(while_mask, input + i);
svbool_t positive = svcmpge_n_s32(while_mask, in, 0);
svint32_t in_positive = svcompact_s32(positive, in);
svst1_s32(while_mask, output + j, in_positive);
i += svcntw();
j += svcntp_b32(while_mask, positive);
while_mask = svwhilelt_b32(i, count);
} while (svptest_any(svptrue_b32(), while_mask));
}
目测协程还是不太成熟,clang的文档可以看看
讲folly实现的。值得一看
讲位运算的。不如看hacker‘s delight
视频
抽象程度 std::function callable,是个能存的对象,能存lambda
lambda只是一个能call的对象。右值。比函数对象能灵活点,匿名函数对象
函数指针也是个能存的,但是比std::function残废,不能保存有状态的lambda,比如有捕获的lambda
手把手教你写any
讲的整型约束。这个在cppcoin 2021上讲过。听不动。很困
开源项目需要人手
- asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群384042845和作者对线
- pika 一个nosql 存储, redis over rocksdb,非常需要人贡献代码胖友们, 感兴趣的欢迎加群294254078前来对线
新项目介绍/版本更新
- unordered_dense hashmap实现,flatmap
- tinylisp 99行c实现lisp
工作招聘
有没有小卖铺缺收银员
看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持!