C++ 中文周刊 第103期

周刊项目地址

公众号

RSS https://github.com/wanghenshui/cppweeklynews/releases.atom

欢迎投稿,推荐或自荐文章/软件/资源等

提交 issue

本周内容不多,线上一堆问题,没空看


资讯

标准委员会动态/ide/编译器信息放在这里

hellogcc本周没更新

文章

之前咱们也发过。这回是中文版本

一些代码技巧,比如全局RE实例,googlebenchmark教学,Popcount使用等等。值得一看

手把手教你糊一个类型擦除,直接贴代码

#include <iostream>
#include <algorithm>
#include <memory>

namespace cwt {

class knight {
public:
    explicit knight(std::size_t strength) 
    : m_strength(strength) {}

    std::size_t get_strength() const  { 
        return m_strength; 
    }
    void who_am_i() const  { 
        std::cout << "i'm a knight\n"; 
    }
private:
    std::size_t m_strength;
};

class skeleton {
public:
    explicit skeleton(std::size_t strength) 
    : m_strength(strength) {}

    std::size_t get_strength() const  { 
        return m_strength; 
    }
    void who_am_i() const  { 
        std::cout << "i'm a skeleton\n"; 
    }
private:
    std::size_t m_strength;
};



class character {
public:
    template<typename T, typename Renderer> 
    character(T&& character, Renderer&& renderer) {
        m_character = std::make_unique<c_model<T, Renderer>>(std::move(character), std::move(renderer));
    }

    void who_am_i() const {
        m_character->who_am_i();
    }

    std::size_t get_strength() const {
        return m_character->get_strength();
    }

    void render() {
        m_character->render();
    }
private:   
    struct c_concept {
        virtual ~c_concept() {}
        virtual std::size_t get_strength() const = 0;
        virtual void who_am_i() const = 0;
        virtual void render() const = 0;
    };
    
    template<typename T, typename Renderer>
    struct c_model : public c_concept {
        c_model(T const& value, Renderer const& renderer) 
        : m_character(value), m_renderer(renderer) {};

        std::size_t get_strength() const override {
            return m_character.get_strength(); 
        }
        void who_am_i() const override {
            m_character.who_am_i();
        }

        void render() const override{
            m_renderer(m_character);
        }

        T m_character;
        Renderer m_renderer;
    };
private:
    std::unique_ptr<c_concept> m_character;
};
} // namespace cwt 


struct knight_renderer{
    void operator()(const cwt::knight& k) const {
        std::cout << "I'll take care of rendering" << std::endl;
    }
};

void knight_render_function(const cwt::knight& knight){
    std::cout << "I could also render a knight" << std::endl;
}

int main(){
    cwt::character character{cwt::knight(10), knight_renderer{}};
    character.render();

    character = cwt::character{cwt::knight(10), [](const cwt::knight& k){
        knight_render_function(k);
    }};
    character.render();

    character = cwt::character{cwt::skeleton(2), [](const cwt::skeleton& s){
        std::cout << "This might be another rendering technique" << std::endl;
    }};
    character.render();
}

直接列代码了

sort

#include <algorithm>
#include <ranges>
#include <iostream>

int main() {
    std::pair<int, std::string_view> pairs[] = {
        {2, "foo"}, {1, "bar"}, {0, "baz"}
    };

    // member access:
    std::ranges::sort(pairs, std::ranges::less{}, 
        &std::pair<int, std::string_view>::first);

    // a lambda:
    std::ranges::sort(pairs, std::ranges::less{}, 
        [](auto const& p) { return p.first; });
}

tranform

#include <algorithm>
#include <vector>
#include <iostream>
#include <ranges>

struct Product {
    std::string name_;
    double value_ { 0.0 };
};

int main() {
    std::vector<Product> prods{7, {"Box ", 1.0}};

    // standard version:  
    std::transform(begin(prods), end(prods), begin(prods), 
        [v = 0](const Product &p) mutable {
            return Product { p.name_ + std::to_string(v++), 1.0};
        }
    );
    for (auto &p : prods) std::cout << p.name_ << ", ";
    std::cout << '\n';

    // ranges version:  
    std::ranges::transform(prods, begin(prods), 
        [v = 0](const std::string &n) mutable {
            return Product { n + std::to_string(v++), 1.0};
        }, 
        &Product::name_);
    for (auto &p : prods) std::cout << p.name_ << ", ";
}

这书好像有中文翻译版本?

consteval auto foo(const auto (&value)[1]) { return value[0]; }
static_assert(42 == foo({42}));

这也是初始化列表的坑爹的地方

降低内存使用

聚合循环

double min = a[0];
for (int i = 1; i < n; i++) {
    if (a[i] < min) { min = a[i] };
}
double max = a[0];
for (int i = 1; i < n; i++) {
    if (a[i] > max) { max = a[i] };
}

了解一波

老生常谈了

涉及到符号,取余数就有点让人看不懂了,比如

-1 % 10 c的表现是-1,而不是9,所以算法得是(-1 % 10) + 10) % 10

小伙很年轻啊,他列了一些常规优化点。这里直接列了,大家自己检查一下

O2, -ffast-math(这个有坑,要注意你的程序是否涉及浮点精度问题,之前讲过)

LTO,

静态编译

PGO,这个大部分都没用 -fprofile-generate -fprofile-use

二进制patch,LLVM BOLT,根据PGO文件修正

no-rtti, no-exception,likely,inline,assume,__restrict____attribute__((pure))

编写cache友好型代码

避免分支切换

SIMD

这个talk还是很值得一看的,光看PPT也能有收获

开源项目需要人手

新项目介绍/版本更新

有没有招聘需要广告的,发我,贴这里


本文永久链接

如果有疑问评论最好在上面链接到评论区里评论,这样方便搜索,微信公众号有点封闭/知乎吞评论

看到这里或许你有建议或者疑问或者指出错误,请留言评论! 多谢! 你的评论非常重要!也可以帮忙点赞收藏转发!多谢支持! 觉得写的不错那就给点吧, 在线乞讨 微信转账