从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态。
每周更新
欢迎投稿,推荐或自荐文章/软件/资源等,请提交 issue
boost 更新https://www.boost.org/users/history/version_1_76_0.html 全是bug fix
简单概括 负数浮点数转化给无符号整型是ub
double dbl = -123.45;
int d_cast0 = (unsigned int)dbl; //可能会被优化成0,尤其是arm平台
int d_cast = (unsigned)(int)dbl;
// d_cast == -123
// works on both.
参考链接2也解释了,在x86平台的汇编和arm平台汇编不同,gcc、clang、msvc都很统一地为x86-64生成了cvttsd2si
,为arm64生成了fcvtzu
fcvtzu导致的0
class iapi {
public:
virtual ~iapi() = default;
virtual auto call() const -> int = 0;
};
struct production_api : iapi { auto call() const -> int override { return {}; } };
struct fake_api : iapi { auto call() const -> int override { return 42; } };
struct app {
const iapi& api;
};
int main() {
auto production = boost::di::make_injector(
boost::di::bind<iapi>.to<production_api>()
);
assert(0 == boost::di::create<app>(production).api.call());
auto testing = boost::di::make_injector(
std::move(production), // include all production bindings
boost::di::bind<iapi>.to<fake_api>() [ boost::di::override ]
);
assert(42 == boost::di::create<app>(testing).api.call());
}
讲了一个string_view到const char* 的bug
// The Case of string_view and the Magic String
// -- by Giovanni Dicanio
#include <stdio.h>
#include <iostream>
#include <string>
#include <string_view>
void SomeCApi(const char* name)
{
printf("Hello, %s!\n", name);
}
void DoSomething(std::string_view name)
{
SomeCApi(name.data());
}
int main()
{
std::string msg = "Connie is learning C++";
auto untilFirstSpace = msg.find(' ');
std::string_view v{ msg.data(), untilFirstSpace };
std::cout << "String view: " << v << '\n';
DoSomething(v);
}
只能说,别这么写,const char*判断结尾和string_view判断结尾并不一致
想让connection只触发一次,触发然后就断开
auto singleShot = [receiver, connection](parameters) {
QObject::disconnect(connection); // WHOPS, we don't have this yet!
receiver->slot(parameters);
};
connection = connect(sender, &Sender::signal, receiver, std::move(singleShot));
这里的问题在connection在后面才生成,lambda要在前面捕获
改进方案
auto connection = std::make_unique<QMetaObject::Connection>();
auto connectionPtr = connection.get();
auto singleShot = [receiver, connection = std::move(connection)](parameters) {
QObject::disconnect(*connection);
receiver->slot(parameters);
};
*connectionPtr = connect(sender, &Sender::signal, receiver, std::move(singleShot)));
难受
qt6新方案
connect(sender, &Sender::signal,
receiver, &Receiver::slot,
static_cast<Qt::ConnectionType>(Qt::SingleShotConnection));
提供了这个功能
那qt5咋办
这里介绍了他们的工具箱库
KDToolBox::connectSingleShot(sender, &Sender::signal, receiver, &Receiver::slot);
sender->causeSignalEmission(); // calls the slot, and breaks the connection
sender->causeSignalEmission(); // does NOT call the slot
第一次causeSignalEmission之后内部自然就disconnection了,也就规避了这个问题,他们的库在这里 https://github.com/KDAB/KDToolBox
直接看代码,继承string,改写char_traits,把traits的方法改写成大小写不敏感就可以了
#pragma once
#include <istream>
#include <ostream>
#include <compare>
#include <string>
#include <locale>
#include <utility>
#include <algorithm>
#include <type_traits>
inline namespace detail
{
template<typename CharT>
inline auto char_ieq(CharT c1, CharT c2, const std::locale& loc = std::locale())
{
return std::toupper(c1, loc) == std::toupper(c2, loc);
};
template<typename CharT>
inline auto char_ilt(CharT c1, CharT c2, const std::locale& loc = std::locale())
{
return std::toupper(c1, loc) < std::toupper(c2, loc);
};
template<typename CharT>
inline auto string_icmp(const CharT* s1, std::size_t n1, const CharT* s2, std::size_t n2, const std::locale& loc = std::locale())
{
if(std::lexicographical_compare(s1, s1 + n1, s2, s2 + n2, [&](CharT c1, CharT c2) { return char_ilt(c1, c2, loc); })) return -1;
if(std::lexicographical_compare(s2, s2 + n2, s1, s1 + n1, [&](CharT c1, CharT c2) { return char_ilt(c1, c2, loc); })) return 1;
return 0;
}
template<typename CharT>
struct char_itraits : std::char_traits<CharT>
{
static auto eq(CharT c1, CharT c2)
{
return char_ieq(c1, c2);
}
static auto lt(CharT c1, CharT c2)
{
return char_ilt(c1, c2);
}
static auto compare(const CharT* s1, const CharT* s2, std::size_t n)
{
return string_icmp(s1, n, s2, n);
}
};
}
template<typename CharT, typename Alloc = std::allocator<CharT>>
class basic_istring : public std::basic_string<CharT, char_itraits<CharT>, Alloc>
{
public:
using base = std::basic_string<CharT, char_itraits<CharT>, Alloc>;
using base::base;
template<typename Traits2, typename Alloc2,
std::enable_if_t<not std::is_same_v<char_itraits<CharT>, Traits2>, void>* = nullptr>
basic_istring(const std::basic_string<CharT, Traits2, Alloc2>& str)
: base(str.data(), str.length()) {}
operator auto () const
{
return std::basic_string<CharT>(this->data(), this->length());
}
template<typename Traits2, typename Alloc2>
std::enable_if_t<not std::is_same_v<char_itraits<CharT>, Traits2>, bool>
friend operator == (const basic_istring& lhs, std::basic_string<CharT, Traits2, Alloc2>& rhs)
{
return string_icmp(lhs.data(), lhs.length(), rhs.data(), rhs.length()) == 0;
}
template<typename Traits2, typename Alloc2>
std::enable_if_t<not std::is_same_v<char_itraits<CharT>, Traits2>, std::strong_ordering>
friend operator <=> (const basic_istring& lhs, std::basic_string<CharT, Traits2, Alloc2>& rhs)
{
return string_icmp(lhs.data(), lhs.length(), rhs.data(), rhs.length()) <=> 0;
}
template<typename Traits2, typename Alloc2>
std::enable_if_t<not std::is_same_v<char_itraits<CharT>, Traits2>, bool>
friend operator == (std::basic_string<CharT, Traits2, Alloc2>& lhs, const basic_istring& rhs)
{
return string_icmp(lhs.data(), lhs.length(), rhs.data(), rhs.length()) == 0;
}
template<typename Traits2, typename Alloc2>
std::enable_if_t<not std::is_same_v<char_itraits<CharT>, Traits2>, std::strong_ordering>
friend operator <=> (std::basic_string<CharT, Traits2, Alloc2>& lhs, const basic_istring& rhs)
{
return string_icmp(lhs.data(), lhs.length(), rhs.data(), rhs.length()) <=> 0;
}
};
using istring = basic_istring<char>;
using iwstring = basic_istring<wchar_t>;
inline auto& operator >> (std::istream& is, istring& istr)
{
std::string temp;
is >> temp;
istr = std::move(temp);
return is;
}
inline auto& operator >> (std::wistream& wis, iwstring& iwstr)
{
std::wstring temp;
wis >> temp;
iwstr = std::move(temp);
return wis;
}
inline auto& operator << (std::ostream& os, const istring& istr)
{
os << istr.c_str();
return os;
}
inline auto& operator << (std::wostream& wos, const iwstring& iwstr)
{
wos << iwstr.c_str();
return wos;
}
inline auto operator ""_is(const char* istr, std::size_t len)
{
return istring(istr, len);
}
inline auto operator ""_iws(const wchar_t* iwstr, std::size_t len)
{
return iwstring(iwstr, len);
}
结论,除非spinlock有范围重叠 overlap(互相引用) 否则不会发生死锁
就是检查是否以xx开头以xx结尾,string小工具