layout | title |
---|---|
post |
第56期 |
从reddit/hackernews/lobsters/meetingcpp摘抄一些c++动态
欢迎投稿,推荐或自荐文章/软件/资源等,请提交 issue
最近非常忙,cppcon的视频没怎么看。更新也有拖延,见谅
标准委员会动态/ide/编译器信息放在这里
编译器信息最新动态推荐关注hellogcc公众号 本周更新 第143期
一个读编译器源码的大纲,可以看看
其实是api设计理念的问题。哎。工作踩坑才会明白
Daniel Lemire博士老活,还是那个数组转字符串最快的问题,如何用avx实现
void to_string_avx512ifma(uint64_t n, char *out) {
uint64_t n_15_08 = n / 100000000;
uint64_t n_07_00 = n % 100000000;
__m512i bcstq_h = _mm512_set1_epi64(n_15_08);
__m512i bcstq_l = _mm512_set1_epi64(n_07_00);
__m512i zmmzero = _mm512_castsi128_si512(_mm_cvtsi64_si128(0x1A1A400));
__m512i zmmTen = _mm512_set1_epi64(10);
__m512i asciiZero = _mm512_set1_epi64('0');
__m512i ifma_const = _mm512_setr_epi64(0x00000000002af31dc, 0x0000000001ad7f29b,
0x0000000010c6f7a0c, 0x00000000a7c5ac472, 0x000000068db8bac72, 0x0000004189374bc6b,
0x0000028f5c28f5c29, 0x0000199999999999a);
__m512i permb_const = _mm512_castsi128_si512(_mm_set_epi8(0x78, 0x70, 0x68, 0x60, 0x58,
0x50, 0x48, 0x40, 0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08, 0x00));
__m512i lowbits_h = _mm512_madd52lo_epu64(zmmzero, bcstq_h, ifma_const);
__m512i lowbits_l = _mm512_madd52lo_epu64(zmmzero, bcstq_l, ifma_const);
__m512i highbits_h = _mm512_madd52hi_epu64(asciiZero, zmmTen, lowbits_h);
__m512i highbits_l = _mm512_madd52hi_epu64(asciiZero, zmmTen, lowbits_l);
__m512i perm = _mm512_permutex2var_epi8(highbits_h, permb_const, highbits_l);
__m128i digits_15_0 = _mm512_castsi512_si128(perm);
_mm_storeu_si128((__m128i *)out, digits_15_0);
}
void to_string_tree_table(uint64_t x, char *out) {
static const char table[200] = {
0x30, 0x30, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35,
0x30, 0x36, 0x30, 0x37, 0x30, 0x38, 0x30, 0x39, 0x31, 0x30, 0x31, 0x31,
0x31, 0x32, 0x31, 0x33, 0x31, 0x34, 0x31, 0x35, 0x31, 0x36, 0x31, 0x37,
0x31, 0x38, 0x31, 0x39, 0x32, 0x30, 0x32, 0x31, 0x32, 0x32, 0x32, 0x33,
0x32, 0x34, 0x32, 0x35, 0x32, 0x36, 0x32, 0x37, 0x32, 0x38, 0x32, 0x39,
0x33, 0x30, 0x33, 0x31, 0x33, 0x32, 0x33, 0x33, 0x33, 0x34, 0x33, 0x35,
0x33, 0x36, 0x33, 0x37, 0x33, 0x38, 0x33, 0x39, 0x34, 0x30, 0x34, 0x31,
0x34, 0x32, 0x34, 0x33, 0x34, 0x34, 0x34, 0x35, 0x34, 0x36, 0x34, 0x37,
0x34, 0x38, 0x34, 0x39, 0x35, 0x30, 0x35, 0x31, 0x35, 0x32, 0x35, 0x33,
0x35, 0x34, 0x35, 0x35, 0x35, 0x36, 0x35, 0x37, 0x35, 0x38, 0x35, 0x39,
0x36, 0x30, 0x36, 0x31, 0x36, 0x32, 0x36, 0x33, 0x36, 0x34, 0x36, 0x35,
0x36, 0x36, 0x36, 0x37, 0x36, 0x38, 0x36, 0x39, 0x37, 0x30, 0x37, 0x31,
0x37, 0x32, 0x37, 0x33, 0x37, 0x34, 0x37, 0x35, 0x37, 0x36, 0x37, 0x37,
0x37, 0x38, 0x37, 0x39, 0x38, 0x30, 0x38, 0x31, 0x38, 0x32, 0x38, 0x33,
0x38, 0x34, 0x38, 0x35, 0x38, 0x36, 0x38, 0x37, 0x38, 0x38, 0x38, 0x39,
0x39, 0x30, 0x39, 0x31, 0x39, 0x32, 0x39, 0x33, 0x39, 0x34, 0x39, 0x35,
0x39, 0x36, 0x39, 0x37, 0x39, 0x38, 0x39, 0x39,
};
uint64_t top = x / 100000000;
uint64_t bottom = x % 100000000;
uint64_t toptop = top / 10000;
uint64_t topbottom = top % 10000;
uint64_t bottomtop = bottom / 10000;
uint64_t bottombottom = bottom % 10000;
uint64_t toptoptop = toptop / 100;
uint64_t toptopbottom = toptop % 100;
uint64_t topbottomtop = topbottom / 100;
uint64_t topbottombottom = topbottom % 100;
uint64_t bottomtoptop = bottomtop / 100;
uint64_t bottomtopbottom = bottomtop % 100;
uint64_t bottombottomtop = bottombottom / 100;
uint64_t bottombottombottom = bottombottom % 100;
//
memcpy(out, &table[2 * toptoptop], 2);
memcpy(out + 2, &table[2 * toptopbottom], 2);
memcpy(out + 4, &table[2 * topbottomtop], 2);
memcpy(out + 6, &table[2 * topbottombottom], 2);
memcpy(out + 8, &table[2 * bottomtoptop], 2);
memcpy(out + 10, &table[2 * bottomtopbottom], 2);
memcpy(out + 12, &table[2 * bottombottomtop], 2);
memcpy(out + 14, &table[2 * bottombottombottom], 2);
}
avx版本要比大表快四倍,我没有编译验证,有空可以贴googlebenchmark跑一下
用宏来反射。不多说
llvm考虑引入生命周期标记,这是整体设计文档
注意span使用,内存布局不同
别用数组存指针,用boost::ptr_vector
别用数组存指针,局部性非常差
古老技术
#include <iterator>
#include <forward_list>
#include <list>
#include <vector>
#include <iostream>
template <typename InputIterator, typename Distance>
void advance_impl(InputIterator& i, Distance n, std::input_iterator_tag) {
std::cout << "InputIterator used" << '\n';
while (n--) ++i;
}
template <typename BidirectionalIterator, typename Distance>
void advance_impl(BidirectionalIterator& i, Distance n, std::bidirectional_iterator_tag) {
std::cout << "BidirectionalIterator used" << '\n';
if (n >= 0)
while (n--) ++i;
else
while (n++) --i;
}
template <typename RandomAccessIterator, typename Distance>
void advance_impl(RandomAccessIterator& i, Distance n, std::random_access_iterator_tag) {
std::cout << "RandomAccessIterator used" << '\n';
i += n; // (5)
}
template <typename InputIterator, typename Distance> // (4)
void advance_(InputIterator& i, Distance n) {
typename std::iterator_traits<InputIterator>::iterator_category category;
advance_impl(i, n, category);
}
int main(){
std::cout << '\n';
std::vector<int> myVec{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // (1)
auto myVecIt = myVec.begin();
std::cout << "*myVecIt: " << *myVecIt << '\n';
advance_(myVecIt, 5);
std::cout << "*myVecIt: " << *myVecIt << '\n';
std::cout << '\n';
std::list<int> myList{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // (2)
auto myListIt = myList.begin();
std::cout << "*myListIt: " << *myListIt << '\n';
advance_(myListIt, 5);
std::cout << "*myListIt: " << *myListIt << '\n';
std::cout << '\n';
std::forward_list<int> myForwardList{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // (3)
auto myForwardListIt = myForwardList.begin();
std::cout << "*myForwardListIt: " << *myForwardListIt << '\n';
advance_(myForwardListIt, 5);
std::cout << "*myForwardListIt: " << *myForwardListIt << '\n';
std::cout << '\n';
}
介绍c++23强类型带来的优势
emplate<double Value> constexpr auto value = Value;
int main() {
std::cout << value<4.2>; // prints 4.2
}
以前只支持整数,现在浮点数也可以了(有啥用???????? )
实现一个能处理溢出的整型,实现一个函数好还是实现一个新类型好?想象int和std::atomic<int>
嵌入式IoT环境 string选型,std::string想用用不了,std::pmr::string想用用不了 string_view可以用
range的算法要比以前的stl算法优雅,建议多用
比如
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
const std::vector numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto even = [](int i) { return 0 == i % 2; };
std::vector<int> temp;
std::copy_if(begin(numbers), end(numbers), std::back_inserter(temp), even);
std::vector<int> temp2(begin(temp)+1, end(temp));
for (auto iter = rbegin(temp2); iter!=rend(temp2); ++iter)
std::cout << *iter << ' ';
}
range
#include <algorithm>
#include <vector>
#include <iostream>
#include <ranges> // new header!
int main() {
const std::vector numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto even = [](int i) { return 0 == i % 2; };
std::ranges::reverse_view rv{
std::ranges::drop_view {
std::ranges::filter_view{ numbers, even }, 1
}
};
for (auto& i : rv)
std::cout << i << ' ';;
}
明显range更好看
Int char short,尽可能用int
用char尽可能unsigned,(笔者注:不过最好标记出你到底用哪个。不同平台默认行为不同 arm默认unsigned x86默认signed)
尽可能用局部变量不用全局变量,如果用,拷贝一份拿过来用
业务场景能用二进制判定就不要用字符串判定,字符串很浪费
Good
#define situation_1 1
#define situation_2 2
#define situation_3 3
int situation_val;
situation_val = situation_2;
. . .
if (situation_val == situation_1)
bad
char situation_val[20];
strcpy(situation_val,"situation_2");
. . .
if ((strcmp(situation_val,"situation_1"))==0)
如果非要用string,尽量用fixed size封装结合mem*算法使用,不要用str*算法 会检查\0
成员函数是怎么工作的,this指针能不能复制一份?
- asteria 一个脚本语言,可嵌入,长期找人,希望胖友们帮帮忙,也可以加群753302367和作者对线