公众号
点击「查看原文」跳转到 GitHub 上对应文件,链接就可以点击了
qq群 点击进入
欢迎投稿,推荐或自荐文章/软件/资源等,评论区留言
本期文章由 Amnesia wyhqaq HNY 赞助 在此表示感谢
老板大气祝老板永远不死
标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 本周更新 2024-01-04 第286期
google在 c++安全上的实践,主要是采用libc++ harden mode
支持字段级别设置attr了 p0609
auto [it, inserted [[maybe_unused]] ] = map.try_emplace(key, value);
支持在条件中展开,类似c++17那个条件中赋值
if (auto [n] = f()) { ... }
while (auto [header, body] = receive_packet()) { ... }
展开绑定到tuple p1061
template <class T>
auto tie_as_tuple(T& x) {
auto& [...xs] = x;
return std::tie(xs...);
}
如果这个能支持,真是有点改变相关工具生态了 magic get/boost pfr可是做了好多脏活
介绍hash combine和 tie组合的。
#include <string>
#include <tuple>
#include <cassert>
#include <cstdint>
#include <boost/functional/hash.hpp>
#include <iostream>
namespace some_lib {
template <typename T>
constexpr void hash_combine(size_t& seed, const T& value)
{
seed ^= std::hash<T>{}(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
}
template <typename... TValues>
constexpr auto combined_hash(const TValues&... values)
{
size_t seed{};
(..., some_lib::hash_combine(seed, values));
return seed;
}
struct HashableForTiedMembers
{ };
template <typename T>
constexpr bool hashing_for_tied_members = false;
template <typename T>
concept HashableForTied = std::derived_from<T, HashableForTiedMembers> || hashing_for_tied_members<T>;
template <HashableForTied T>
struct std::hash<T>
{
size_t operator()(const T& value) const
{
auto hasher = [](const auto&... args) {
return combined_hash(args...);
};
return std::apply(hasher, value.tied());
}
};
template <typename T>
concept Hashable = requires {
{ std::hash<T>{}(std::declval<T>()) } -> std::convertible_to<size_t>;
};
/////////////////////////////////////////////////////////////////////////
// Person class - opt-in through inheritance
struct Person : HashableForTiedMembers
{
std::string first_name;
std::string last_name;
std::uint8_t age;
Person(std::string first_name, std::string last_name, std::uint8_t age)
: first_name{std::move(first_name)}
, last_name{std::move(last_name)}
, age{age}
{
}
auto tied() const
{
return std::tie(first_name, last_name, age);
}
bool operator==(const Person& other) const
{
return tied() == other.tied();
}
auto operator<=>(const Person& other) const
{
return tied() == other.tied();
}
};
static_assert(Hashable<Person>);
//////////////////////////////////////////////////////////////////////////
// AggregatePerson - opt-in through variable template specialization
struct AggregatePerson
{
std::string first_name;
std::string last_name;
std::uint8_t age;
auto tied() const
{
return std::tie(first_name, last_name, age);
}
};
template <>
constexpr bool hashing_for_tied_members<AggregatePerson> = true;
int main()
{
Person p1{"John", "Doe", 33};
Person p2{"John", "Doe", 33};
Person p3{"John", "Don", 44};
assert(p1 == p2);
assert(p2 < p3);
assert(std::hash<Person>{}(p1) == std::hash<Person>{}(p2));
assert(std::hash<Person>{}(p1) == std::hash<Person>{}(p3));
AggregatePerson ap1{"John", "Doe", 30};
AggregatePerson ap2{"John", "Doe", 30};
AggregatePerson ap3{"John", "Dog", 30};
assert(std::hash<AggregatePerson>{}(ap1) == std::hash<AggregatePerson>{}(ap2));
assert(std::hash<AggregatePerson>{}(ap1) != std::hash<AggregatePerson>{}(ap3));
return std::hash<Person>{}(p1);
}
其实他这个设计就是hash_append
template <class HashAlgorithm>
friend void hash_append(HashAlgorithm& h, X const& x) noexcept
{
//
}
他这个写法就是把hash算法和x拆出来,x本身转pack 方便归一计算,用的tie 避免开销
combined_hash其实就是hash_append 只不过算法h不能定制
不知道读者们了不了解n3980 hash_append 不了解没关系。就是函数接口定制和这里的代码一个意思
非常搞笑的场景,同样的hashmap float 做key和 int做key冲突率不同 因为值域不同。float表达式导致的
针对float做key要注意hash算法
和shared_ptr差不多,为了原子 使用tag pointer 用特殊字段做spinlock 代码在这里
while (!_M_val.compare_exchange_strong(__current,
__current | _S_lock_bit,
__o,
memory_order_relaxed))
{
_GLIBCXX_TSAN_MUTEX_TRY_LOCK_FAILED(&_M_val);
#if __glibcxx_atomic_wait
__detail::__thread_relax();
#endif
__current = __current & ~_S_lock_bit;
_GLIBCXX_TSAN_MUTEX_TRY_LOCK(&_M_val);
}
_GLIBCXX_TSAN_MUTEX_LOCKED(&_M_val);
return reinterpret_cast<pointer>(__current);
}
直接贴代码
#include <bitset>
#include <ostream>
#include <type_traits>
#include <utility>
// Helper class for bitwise flag-like operations on scoped enums.
//
// This class provides a way to represent combinations of enum values without
// directly overloading operators on the enum type itself. This approach
// avoids ambiguity in the type system and allows the enum type to continue
// representing a single value, while the BitFlags can hold a combination
// of enum values.
//
// Example usage:
//
// enum class MyEnum { FlagA = 1 << 0, FlagB = 1 << 1, FlagC = 1 << 2 };
//
// BitFlags<MyEnum> flags = { MyEnum::FlagA, MyEnum::FlagC };
// flags.Unset(MyEnum::FlagA);
// if (flags.IsSet(MyEnum::FlagC)) {
// // ...
// }
//
// flags |= MyEnum::FlagB;
// BitFlags<MyEnum> new_flags = ~flags;
template <typename T>
class BitFlags {
using UnderlyingT = std::underlying_type_t<T>;
public:
constexpr BitFlags() : flags_(static_cast<UnderlyingT>(0)) {}
constexpr explicit BitFlags(T v) : flags_(ToUnderlying(v)) {}
constexpr BitFlags(std::initializer_list<T> vs) : BitFlags() {
for (T v : vs) {
flags_ |= ToUnderlying(v);
}
}
// Checks if a specific flag is set.
constexpr bool IsSet(T v) const {
return (flags_ & ToUnderlying(v)) == ToUnderlying(v);
}
// Sets a single flag value.
constexpr void Set(T v) { flags_ |= ToUnderlying(v); }
// Unsets a single flag value.
constexpr void Unset(T v) { flags_ &= ~ToUnderlying(v); }
// Clears all flag values.
constexpr void Clear() { flags_ = static_cast<UnderlyingT>(0); }
constexpr operator bool() const {
return flags_ != static_cast<UnderlyingT>(0);
}
friend constexpr BitFlags operator|(BitFlags lhs, T rhs) {
return BitFlags(lhs.flags_ | ToUnderlying(rhs));
}
friend constexpr BitFlags operator|(BitFlags lhs, BitFlags rhs) {
return BitFlags(lhs.flags_ | rhs.flags_);
}
friend constexpr BitFlags operator&(BitFlags lhs, T rhs) {
return BitFlags(lhs.flags_ & ToUnderlying(rhs));
}
friend constexpr BitFlags operator&(BitFlags lhs, BitFlags rhs) {
return BitFlags(lhs.flags_ & rhs.flags_);
}
friend constexpr BitFlags operator^(BitFlags lhs, T rhs) {
return BitFlags(lhs.flags_ ^ ToUnderlying(rhs));
}
friend constexpr BitFlags operator^(BitFlags lhs, BitFlags rhs) {
return BitFlags(lhs.flags_ ^ rhs.flags_);
}
friend constexpr BitFlags& operator|=(BitFlags& lhs, T rhs) {
lhs.flags_ |= ToUnderlying(rhs);
return lhs;
}
friend constexpr BitFlags& operator|=(BitFlags& lhs, BitFlags rhs) {
lhs.flags_ |= rhs.flags_;
return lhs;
}
friend constexpr BitFlags& operator&=(BitFlags& lhs, T rhs) {
lhs.flags_ &= ToUnderlying(rhs);
return lhs;
}
friend constexpr BitFlags& operator&=(BitFlags& lhs, BitFlags rhs) {
lhs.flags_ &= rhs.flags_;
return lhs;
}
friend constexpr BitFlags& operator^=(BitFlags& lhs, T rhs) {
lhs.flags_ ^= ToUnderlying(rhs);
return lhs;
}
friend constexpr BitFlags& operator^=(BitFlags& lhs, BitFlags rhs) {
lhs.flags_ ^= rhs.flags_;
return lhs;
}
friend constexpr BitFlags operator~(const BitFlags& bf) {
return BitFlags(~bf.flags_);
}
friend constexpr bool operator==(const BitFlags& lhs, const BitFlags& rhs) {
return lhs.flags_ == rhs.flags_;
}
friend constexpr bool operator!=(const BitFlags& lhs, const BitFlags& rhs) {
return lhs.flags_ != rhs.flags_;
}
// Stream output operator for debugging.
friend std::ostream& operator<<(std::ostream& os, const BitFlags& bf) {
// Write out a bitset representation.
os << std::bitset<sizeof(UnderlyingT) * 8>(bf.flags_);
return os;
}
// Construct BitFlags from raw values.
static constexpr BitFlags FromRaw(UnderlyingT flags) {
return BitFlags(flags);
}
// Retrieve the raw underlying flags.
constexpr UnderlyingT ToRaw() const { return flags_; }
private:
constexpr explicit BitFlags(UnderlyingT flags) : flags_(flags) {}
static constexpr UnderlyingT ToUnderlying(T v) { return static_cast<UnderlyingT>(v); }
UnderlyingT flags_;
};
template<typename...Args>
struct maker
{
std::tuple<Args&&...> m_args;
maker(Args&&... args) : m_args((Args&&)args...) {}
template<typename T>
operator T() {
return std::make_from_tuple<T>(std::move(m_args));
}
};
template<typename D>
struct OwnerHelper
{
template<typename...Args>
auto Owned(Args&&... args)
{ return maker<Args&&..., D*>((Args&&)args..., static_cast<D*>(this)); }
};
struct Widget : Object, OwnerHelper<Widget>
{
Property<int> Height = Owned("Height", 10);
Property<std::string> Name = Owned("Name", ""s);
Event<NameChangedHandler> NameChanged = Owned("NameChanged");
};
通过crtp绕一下传this 当然如果有deducing this可以这样
struct OwnerHelper
{
template<typename O, typename...Args>
auto Owned(this O&& self, Args&&... args)
{
return maker<Args&&..., O*>((Args&&)args..., &self);
}
};
struct Widget : Object, OwnerHelper
{
Property<int> Height = Owned("Height", 10);
Property<std::string> Name = Owned("Name", ""s);
Event<NameChangedHandler> NameChanged = Owned("NameChanged");
};
列举几个经典bug代码
realloc失败
int sceNetAdhocMatchingSetHelloOpt(int matchingId,
int optLenAddr, u32 optDataAddr)
{
....
if (optLenAddr > context->hellolen)
{
hello = realloc(hello, optLenAddr);
}
....
}
这里realloc失败返回null正好给hello覆盖了。原来的hello泄漏
拼写错误一个例子
static const TypeToNameMap& get_type_to_name_tbl() {
static const TypeToNameMap type_to_name_tbl = {
....,
{"Abs", Type::Eltwise}, // <=
....,
{"SoftPlus", Type::Eltwise}, // <=
....,
{"Abs", Type::Math}, // <=
....,
{"SoftPlus", Type::Math}, // <=
....,
};
return type_to_name_tbl;
}
继承忘记final导致误用,代码不列了有点蠢
死代码/复制粘贴错误也不列了
ifelse匹配
const qdGameObjectStateWalk* qdGameObjectMoving::current_walk_state() const
{
const qdGameObjectState* st = get_cur_state();
if(!st || st -> state_type() != qdGameObjectState::STATE_WALK){
#ifndef _QUEST_EDITOR
st = last_walk_state_;
if(!st || st -> state_type() != qdGameObjectState::STATE_WALK)
st = get_default_state();
else
st = get_default_state();
if(!st) st = get_state(0);
#endif
}
....
}
else忘记写#了。
不可见字符
static const char *script_list[][2] = {
....
{ "Myanmar / Burmese", "Mymr" },
{ "Nag Mundari", "Nagm" },
{ "Nandinagari", "Nand" },
....
}
以及数组溢出,代码不列了
本期更新距离上一期差了一个月,作者沉迷街霸是原因之一
另外的原因就是,感觉很累,有一点重复自己。在自媒体的内容想想搞一点突破,涨涨流量
但是比起去年接到商单,今年只接到图书推广单子,赠书,书我转手送了
比较惨淡
考虑了带货,带货金额没有押金多
另外就是蹭热度/日更段子阅读量更好。而周更内容实际上比较一般
确实迷茫了。反复重复自我,还是深耕一下,只讲专题,周刊改成月刊形式?
资料是看不完的,周刊总感觉只是泛泛而谈没啥深度内容
一方面,读者需要深度内容,一方面读者也看tips之类的知识点
我感觉我有点搞不过来,时间真不够用
欢迎大家提出建议意见