Concept 對 C++ 有什麼影響,它和 Rust 的泛型 Bound 和 Trait 有點類似?
C++ 標準里的 Concepts 是什麼?它對 C++ 有什麼影響?會不會因為又多了一個概念,讓它更難學了?
它好像和 Rust 的泛型 Bound 和 Traits 有點類似?還有,它和和 Haskell 有什麼聯繫?
在C++11移除Concept的時候,Michael Wong曾經說過一句話:"I am sure this will not be the last we will hear of it." 而在C++17加入Concept的時候,Eric Niebler發了這麼一條Twitter
vector&
multiset&
auto vi = find(v, 7); // calls sequence overload
auto si = find(s, 7); // calls associative container overload
而非再考慮使用SFINAE。
有了這一層「類型系統」,也可以有效的改善錯誤提示信息,因為現在的模板參數有了「類型」了,而不是再一層一層的向下轉換,直到int, char等具體類型才停下來。而模板如今的痛苦早在Bjarne書寫《C++語言的設計與演化》的時候就意識到了,然而很遺憾的是,正式開始想辦法解決這個問題是直到2000年才開始,而更遺憾的是C++11把這個給斃掉了。所幸在Andrew Sutton, Bjarne, STL之父Alex,印第安納大學若干愛好者等人的努力下,重新設計Concept,最終在C++17進入。
對於Concept來說,很容易與Java, C#的interface比較,然而它們是不同的,因為Concept與Concept之間沒有interface那樣的繼承關係。
而有了Concept以後,STL也將會使用Concept重寫,所以即使你不直接使用Concept,你也能享受到Concept的好處。
而有關Concept的討論,我在幾個月前在Reddit上看到了一個非常好的討論,在這裡面包括了Concept的提案與GCC Concept的實現者Andrew Sutton的一些討論與回復,可以參考一下:Eric Niebler on Twitter: "The Concepts TS was voted out today! Concepts are (almost) an ISO standard. Congrats, A. Sutton. This will change everything. @isocpp #cpp" : cpp不嚴格地講,Concepts Lite是個語法糖,包裝的是SFINAE這個已有feature。所以想弄清楚Concepts Lite,請自行學習SFINAE。當然type_traits也要看一下。
值得一提的是定義一個concepts就如同定義一個trait一樣。沒有任何新的語言特性混進來。這種設計滿足了大批有語義(不是語法)特性潔癖的C++程序員:)
此外,Concepts Lite只檢查caller side,不檢查definition,這是它和Rust的traits,Haskell的type class的一個不同。另外一個是用戶不需要顯式讓一個類型「實現」一個concept(因為concept就是type trait嘛),這點和Haskell不同;其差別類似Java的interface和Go的interface的差別。
可刷一遍這個:Concepts Lite: Constraining Templates with Predicates好的。
為了拯救不開心...
詳情看未鵬的這篇blog http://blog.csdn.net/pongba/article/details/1726031concept主要是為了解決sfinae的類型約束問題。
因為c++模板在編譯器不對模板約束條件做類型檢查,事實上也做不了那麼多類型檢查,只對實例化代碼進行類型檢查。就會有一些模板用了好一段時間沒問題,結果這次加上新類型的時候就報錯了的情況。
同時因為模板的泛型特徵不區分具體類型,只判斷能否編譯通過,就會產生很多潛在bug。
比如:
template&
void fun(T stream) { stream &<&< 1; }
理想的情況下是調用
std::fstream file;
fun(file);
可實際情況下,寫了
int i;
fun(i);
也能編譯通過,這就是sfinae產生的bug。
如果用concept解決這個問題,就要定義:
auto concept Constructable&
template& 用構造函數來約束T的類型,int這種基本類型沒有構造函數,就會報錯。 而trait,則是用模板偏特化的方法,區分處理各種類型。 比如以上的bug,可以用 template& 解決,is_int::value此時就是一個區分類型的trait。 同理可以推廣到其他類型上,此後 就會編譯期報錯了。 與interface面向類不同,concept是對模板的約束,並非強制類型檢查。 沒有implement全部介面的基類編譯不會通過,但是concept只要滿足約束條件即可使用模板,未滿足條件只是不能使用該模板而已。
void fun(T stream) { stream &<&< 1; }
template &
struct is_int
{
static const bool value = false;
};
template &<&>
struct is_int&
{
static const bool value = true;
};
void fun(T stream)
{
static_assert(true != is_int&
stream &<&< 1;
}
int i;
fun(i);
推薦閱讀:
※有哪些鍛煉編程能力的 C++ 項目?
※Rust 和 C++ 有哪些優劣?
※我是初學c++者,我想達到熟練使用c++的程度,我就想知道達到什麼地步才能算是熟練使用呢?
※Unity 5 發布了,但是否 Unity 做的遊戲與 Unreal 相比要顯得粗糙很多?
※GitHub 上都有哪些值得關注學習的有趣的 C++ 開源項目?