您當前的位置:首頁 > 攝影

從is_constexpr說開去

作者:由 陳林熙 發表于 攝影時間:2017-08-12

今天到isocpp的googlegroup上提了一個is_constexpr的建議,然後說is_constexpr是不可能的,因為is_constexpr是具有高度爭議的,可能違反ODR原則。其實按我的想法,is_constexpr不過是個折中辦法了,最正確的做法是打破constexpr一切限制,即便是用上ASM依然能夠返回常量,也就是隻要輸入是常量,結果是確定性的,那麼一定返回常量,對ASM可以用模擬的方式來實現。當然了,這又太複雜了。

雖然早就有人提出了這個問題,不過其實是不一樣的,因為以前沒有if constexpr()這樣的語法,就算有is_constexpr,實際寫起來也是很繁雜的。但是有了if constexpr就不用繞一下了,因為如果這編譯器選擇的分支太多,要繞的函式太多,最後都能就是放棄,我以前寫了一個容器類,本來是設計成儲存方式為棧,固定堆,可變堆,連結串列,是否支援Cap,Cap的增長方式,這些特性都是用模板控制的,最後只能說勉強實現了,連結串列沒實現,其實本來我還有一些想法,不過算了,就是這個類都折騰得我夠嗆,當然現在有了if constexpr和Concept(後面會說)就要容易好些,不過還是有問題,比如結構選擇的問題,也要用一個類來繞,如果特性與結構相關,並且這樣特性很多,那麼最後結果可能還是放棄。

至於說什麼違反ODR。。。其實都是藉口,想要解決的問題,總有辦法解決。因為我看GCC裡原始碼裡,有is_internal_constexpr這樣的函式,就是說,這個功能早就有了,只不過是沒有開放出介面而已。

你看gcc裡面有些__builtin函式,其實這些函式就可以根據引數的來選擇實現方式,比如__builtin_memcpy若count是常量且小,它會生成內嵌的程式碼,若大或是變數又會生成高效的程式碼,如果用了SIMD的編譯選項,還可以生成SIMD程式碼,但是這種好處只是__builtin的特權,沒有is_constexpr的支援,我們自己是無法寫出這樣的函式的(只在極其有限的情況下能寫出這樣的函式)。

當然即使有了is_constexpr,其實也是不能寫出一個完美函式或類,所謂完美函式或類,是指你寫了一個函式或類,既能用作常量的情況,也能用作變數情況,並且,這個類和函式生成的程式碼(>=O2),和你分別寫兩個常量版和非常量版的函式或類生成程式碼,在效能和體積上是相當的(根據我的經驗,一旦滿足這樣的條件,極可能生成的程式碼是二進位制相同的)。因為constexpr目前還有一些限制(C++11的時候限制更多)。只能說有了is_constexpr,在某些情況下,能寫出完美函式或類。

雖然過去有人提過,提過就不能提了嗎,Concept從C++11就開始提了,到C++17還沒落實,不過我估計C++20就會落實,因為現在的主流編譯器CLang,GCC都支援Concept,估計MS很快也會跟上。至於為什麼C++17沒有落實Concept,按照網上一篇文章說法,是因為時間不夠,寫這個Concept TS的人和實現Concept的是同一個人,因為只有4個月時間了,所以沒法落實,而實際的情況也是這樣Concept現在仍然有一些bug,畢竟成為一個正式標準的一部分,雖然不能說完全無錯,但是也不能有太多bug。

當然了Concept有一些複雜性的,如它引入了More constraints概念,光是這個More constraints其實細細一想,裡面還是有很多的複雜性的。

More constraints是指若一個constraints比另一個constraints更嚴格,則優先匹配嚴格的。那麼這種嚴格性如何定義呢,原來More constraints把這些約束分解成原子約束,然後根據原子約束的包含關係來判斷,那麼就有很多情況了,因為首先原子約束如何定義,比如C1=sizeof。。。(U)>1;C2=sizeof。。。(U)>2;

顯然C2=>C1,但是這種情況的原子如何定義。還有就是語義上是包含的,但是在定義的時候走的是不同的途徑,那麼可能就不會包含。

其它一些特性

Concept是否支援繼承,特化(目前不支援),Concept能否和using配合使用(目前不支援),requires是否支援lambda表示式(目前不支援)。

當然了還有Concept是否支援短路表示式(目前支援),Concept的巢狀時解析順序等等問題。

是否支援Concept<。。。>語法,目前支援不過有些問題。

Concept使用語法問題,Concept支援template Addable{T}這樣的語法,甚至是Addable add(Addable a,Addable b)這樣語法簡便語法,不過這些語法比起標準式總有這樣那樣的限制,如無法使用。。。語法,甚至內部不能對Addable這樣的名字作為進一步的判斷。

當然了我是希望,能夠放寬對這些簡寫形式的限制,因為標準式長了一些。

其它還有CV屬性的問題,是否支援模板模板引數的問題。

作為C++編譯器的開發者,考慮的肯定是和一個C++的使用者是不同的,比如短路表示式的問題,由於Concept支援多種語法,並且這些語法可以(不反對)同時起作用,那麼就要指定一個匹配順序的規則,並且這些Concept還可以和Enable If同時起作用。

如果Concept要成為標準,那麼這些問題就必需要有一個明確的規則,就目前看來,這些問題只有一些鬆散的描述。

當然了,Concept初衷本來是建立一種型別檢查的工具,不過現在已經演變成了一種泛型程式設計的工具了。

【注】

本文只是Essay性質,對Concept的描述不保證絕對正確,由於Concept還在進化中,關於它的描述以最終標準為準。

標簽: concept  constexpr  語法  函式  C++