看了知乎這篇
之後才知道inline
博大精深
先看程式碼
1 | inline void f(void) { } |
用g++編譯這段程式,不管下-O2
或是-O0
都編譯的過
而如果用gcc編譯的話,-O0
會出現unrefernce error,但如果下-std=gnu89
又沒問題
根據知乎上面寫的,正確的修復方式應該為
1 | extern void f(void) {} |
C++跟C99之後,語意分歧點越來越多啊
看了知乎這篇
之後才知道inline
博大精深
先看程式碼
1 | inline void f(void) { } |
用g++編譯這段程式,不管下-O2
或是-O0
都編譯的過
而如果用gcc編譯的話,-O0
會出現unrefernce error,但如果下-std=gnu89
又沒問題
根據知乎上面寫的,正確的修復方式應該為
1 | extern void f(void) {} |
C++跟C99之後,語意分歧點越來越多啊
Rollback changelist是很常做的事情,不過在git這種分散式控制系統就有點麻煩了
假設我們現在有這樣的Commit history
1 | $ git log --oneline |
而我們現在要退回ver 2
該怎麼做
直接開大絕
1 | $ git reset 10dd293 --hard |
然而自己一個人玩玩還行,團體行動絕對沒有人建議這麼做
1 | $ git checkout 10dd293 -b v2 # 切換新分支 |
可以看見HEAD指向v2的new commit了,比較一下
1 | $ git diff HEAD..10dd293 |
然後可以把v2推向remote了
1 | $ git push origin master |
三者等價
再不寫點東西,這邊就長草了
這幾天在看go-redis
專案,顧名思義就是在golang當中對redis操作的程式庫
其中有一段程式碼是這樣
1 | func ExampleClient() { |
結果去redis.go
裡面查看,找不到Set
這個函數的實作
只好用grep去找哪邊可能實作這個函數
最後讓我在command.go
找到
1 | func (c *cmdable) Set(key string, value interface{}, expiration time.Duration) *StatusCmd { |
在同一個檔案中找到cmdable
的定義
1 | type cmdable struct { |
回頭看我們的redis.go
,發現一樣的東西
1 | type baseClient struct { |
因為有同樣的Singature,所以可以把baseClient
當cmder`來用
雖然找到了我想要的答案,不過我不喜歡這方法
由於我找不到Set這函數,於是我需要grep找到可能的實作 => 發現baseClient和cmadble的相似處
那為什麼不直接用繼承關係就好了,這樣可以找到相依性
1 | struct ICmdable { |
這樣可以看出baseClient
必須繼承’ICmdable’這個介面
不過可能引申出多重繼承的問題,老話一句,沒有什麼方法一體適用
現在在科技業沒講個深度學習會被翻白眼,Prototype是一回事,放進Product又是另一回事
之前一般來說通用信的選擇是Tensorflow,雖說Prototype跟Product可以一起完成
不過C++那端難寫就算了,Python那邊也麻煩的要死,沒太多精力搞這個
後來看到PyTorch,Onnx,以及Caffe2改變了想法
用易學易用的PyTorch建構出Onnx Mdoel,透過Onnx轉換成Caffe2 Model,加上對終端最佳化的Caffe2 Library
變成另外一種可行的解法
我自己的實驗結果就放在 GitHub
其中C++ Demo的部分是從Caffe2 Android Example那邊學來的
雖然看起來不多,不過真正讓他可以動倒是花了不少時間
過年前有個工作需求,需要跨平台的AES硬體加速功能,研究了一下幾種方案
– Openssl (增加相依性,加上編譯時需要設定改來改去)
– Runtime JIT (先判斷CPU種類,然後根據CPU類型生成組合語言,小小的玩意哪需要玩這麼大)
– libkcapi – Linux Kernel Crypto API User Space Interface Library
覺得最後一種方式不錯,不過我只需要AES,其他地方可以拿掉
因此對這Project進行二次加工,產生了KCAES這個專案
不過在進行AES CBC運算時,發現長度超過64K就會報錯,只好對超過64K的Block進行二次加工
不需要其他的相依性,只要把檔案放進自己的專案,加入編譯即可
去英國晃了一圈,回來還是寫點東西,免得生疏了
沒什麼好說的,就是static_assert改成允許單參數,直接看程式碼
Before C++17
1 | static_assert(sizeof(short) == 2, "sizeof(short) == 2") |
After C++17
1 | static_assert(sizeof(short) == 2) |
對Header-Only library特別有用,不過我不喜歡Header-Only library
原先如果要定義一個變數,要在header宣告,在source code裡面定義
現在可以直接寫在header裡了
Before C++17:
1 | // foo.h |
After C++17:
1 | // foo.h |
原先C++14辦不到,C++17允許的能力
1 | constexpr int Func(int x) |
不過我還沒想到這東西可以做啥
原本我還搞不懂capture [this]
和capture [*this]
有什麼不同,自己寫了一個範例之後搞懂了
1 | #include <string> |
capture [*this]
相當於上面的[self = *this]
,會將原有的物件複製一份
而[this]
不會
C++11引進了Attribute,在C++17增加了更多attributes,如[[fallthrough]]等
就是把GCC/VC的attribute標準化,不多做解釋了
至於STL的加強就不特別寫了, Guaranteed Copy Elision可能要另外寫
就先寫到這了
以往我們可能寫出類似這樣的程式碼
1 | #include <string> |
如今我們可以寫成這樣
1 | #include <string> |
省去了很多的冗於
如果配合variant
來使用,程式碼可以寫成這樣
1 | #include <string> |
在c++17之前,寫了很多這樣子的程式碼
1 | std::mutex m; |
為什麼函數可以推導出型別,而類型不行,於是C++17放寬了這條件
1 | std::lock_guard lock(m); |
當然,也是有explicit class deduction guide的,請參考reference
<auto>
目前看起來沒什麼用的feature
未用c++17前程式碼長這樣
1 | template <typename T, T v> |
用了C++17後
1 | template <auto v> |
早該有的東西, 結果拖到這麼後面才加進來
1 | namespace X { |
現在可以寫成
1 | namespace X::Y { |
以加法為範例
在c++17之前的寫法
1 | template<typename T> |
把sum寫成兩部分,雖然不是不行,不過總覺得被切割加重學習負擔
用上if constexpr
1 | template<typename T, typename... Args> |
好一點了,用上Fold expression會變成怎樣
1 | template<typename ...Args> |
跟if constexpr
方法比是更精簡了一點,不過多了一堆語法規則,實在不太划算
— A Tour of C++ 17: If Constexpr
— C++17中的deduction guide
— C++17 Fold Expressions
對於C++17特性的文章已經有很多了,歸納自己的想法寫成幾篇文章
覺得很有用的特性之一
在沒有C++17之前,程式碼大概長這樣
1 | void test() { |
在C++17之後
1 | void test() { |
在沒有Structure Binding時,程式碼大概長這樣
1 | std::tuple<int, double> stuff(); |
或者是
1 | int i; |
不過都比不上
1 | auto [i, d] = stuff(); |
傳統的
1 | errcode doSomething(obj *out_value); |
之後會變成
1 | std::tuple<obj, errcode> doSomething(); |
有點golang的感覺
不過看看以下程式碼
1 | struct Foo |
結果出乎意料,不是大家所想的copy by value,而是copy by reference
Compiler大概做的是像這樣
1 | int main() |
還有下面這個範例
1 | struct X { int i = 0; }; |
– c++
編譯不過,因為這是bind to const reference
– auto & [d] = makeX()
編譯不過,因為left reference不能bind to right value
– f++
編譯不過,理由同第一條
看看以下程式有什麼不一樣
1 | #include <iostream> |
和
1 | template <typename T> |
差異就在於auto和decltype的用途不太一樣,auto會去掉reference,而decltype(auto)不會
C++11也可以達到decltype(auto)的方式,不過寫法比較繁瑣
1 | template <typename T> |
cgroup是linux用來限制program使用Computer resource的一種方法
也是Docker的基礎
首先先安裝cgroup
1 | $ sudo apt install cgroup-bin |
不用看也知道他絕對吃滿cpu resource
所以該怎麼限制,例如只讓他吃20%的CPU
先建立cgroup的群組
1 | $ cd /sys/fs/cgroup/cpu # 管理CPU資源的地方 |
接著把我們程式限制的規則加入群組 以下動作需要root權限,sudo無法執行
1 | $ echo 20000 > calm/cpu.cfs_quota_us # 預設值是100000,20000正好是20% |
接著我們就能看到程式CPU使用率就只剩20%了
也可以用自定義規則的方式
1 | $ sudo cgcreate -g cpu:calm # 一樣是建立 cpu calm |
如果要執行程式的話
1 | $ sudo cgexec -g cpu:calm python busy.py |
跟上面有同樣的效果