c++ 17介绍
作者:hearts zh
鏈接:https://www.zhihu.com/question/32222337/answer/55238928
來源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
其實現(xiàn)在的proposal很多很多,不出意外也會有相當(dāng)一部分沒時間加進(jìn)c++17。c++17會是一個大更新,下一個小修補(bǔ)會是c++20
我個人認(rèn)為從發(fā)展角度來說,c++目前最需要的,是module,網(wǎng)絡(luò)庫,以及更完善的并行庫。我只稍微搬一下Stroustrup桑今年最新提交的提案,提到了他認(rèn)為的c++17是需要包括哪些東西。
全文具體鏈接。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4492.pdf
首先,C++永久性的目的就是運行效率。無論怎么設(shè)計都不會違背這一點。
Whatever we do, we should preserve C++’s fundamental strengths:
? A direct map to hardware (initially from C)
? Zero-overhead abstraction (initially from Simula)
Depart from these and the language is no longer C++.
1. 關(guān)于大規(guī)模軟件系統(tǒng)的支持
2. 關(guān)于并行
3. 語言用法簡化
以上就是stroustrup桑眼里的c++17應(yīng)該大概支持這些。當(dāng)然不是一個完整列表,不包括一些庫的改進(jìn)和語法小改進(jìn)。 不要想啦,C++ 17 毛都沒有。。。沒有 Module, 沒有 Coroutine, 沒有 Ranges,沒有 Reflection,沒有 Contracts,沒有……
唯一有希望的 Concepts 爭議很大。。也玄。
Network TS 也玄。
所以,……
--------------------------------------------------------------------------------------------------------------------------------
我的天,看到這個問題我激動得不知道說些什么好。在 BS 的那篇 Thoughts about C++ 17 里面已經(jīng)提到了很多提案了。我說一點我研究過的吧,算是拋磚引玉:
先說一些開胃菜吧。
For direct list-initialization:
1.For a braced-init-list with only a single element, auto deduction will deduce from that entry;
2.For a braced-init-list with more than one element, auto deduction will be ill-formed.
namespace A {namespace B { namespace C { //… } } }
<img src="https://pic3.zhimg.com/9702ddd9a5ee7fd1e5fe91c003916fd2_b.png" data-rawheight="717" data-rawwidth="964" class="origin_image zh-lightbox-thumb" width="964" data-original="https://pic3.zhimg.com/9702ddd9a5ee7fd1e5fe91c003916fd2_r.png">注意!Sortable可不是Java/C#里的Interface,它叫做Concept。注意!Sortable可不是Java/C#里的Interface,它叫做Concept。
T& operator[](size_t i) [[expects: i < size()]]; ArrayView(const vector<T>& v) [[ensures: data() == v.data()]]; 那么不滿足這些conditions會發(fā)生什么呢?提案中說是“implemention-defined”。而且應(yīng)該允許每個TU獨立打開所有的測試,關(guān)閉所有,打開/關(guān)閉pre,打開關(guān)閉post。
void f(FILE* file) { fseek(file,9,SEEK_SET); } //proposed new C++ code void f(FILE* file) { file->fseek(9,SEEK_SET); //nice autocomplete after "->" } 不過現(xiàn)在這個提案還有很多細(xì)節(jié)在商討。
說了一些我了解的Core Language特性,說一些庫的東西吧!先說點小東西
template <class F, class Tuple, std::size_t... I> constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, std::index_sequence<I...>) { return std::invoke(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...); // Note: std::invoke is a C++17 feature } template <class F, class Tuple> constexpr decltype(auto) apply(F&& f, Tuple&& t) { return apply_impl(std::forward<F>(f), std::forward<Tuple>(t), std::make_index_sequence < std::tuple_size<std::decay_t<Tuple>>::value > {}); }
template<typename Iterator, typename = void> struct reference_type { using type = decltype(*declval<Iterator>()); // no reference, use operator* }; template<typename Iterator> struct reference_type<Iterator, void_t<typename Iterator::reference> > { using type = typename Iterator::reference; //I have a reference };
再說說大的。目前這些都屬于 TS 。
鏈接:https://www.zhihu.com/question/32222337/answer/55238928
來源:知乎
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
其實現(xiàn)在的proposal很多很多,不出意外也會有相當(dāng)一部分沒時間加進(jìn)c++17。c++17會是一個大更新,下一個小修補(bǔ)會是c++20
我個人認(rèn)為從發(fā)展角度來說,c++目前最需要的,是module,網(wǎng)絡(luò)庫,以及更完善的并行庫。我只稍微搬一下Stroustrup桑今年最新提交的提案,提到了他認(rèn)為的c++17是需要包括哪些東西。
全文具體鏈接。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4492.pdf
首先,C++永久性的目的就是運行效率。無論怎么設(shè)計都不會違背這一點。
Whatever we do, we should preserve C++’s fundamental strengths:
? A direct map to hardware (initially from C)
? Zero-overhead abstraction (initially from Simula)
Depart from these and the language is no longer C++.
1. 關(guān)于大規(guī)模軟件系統(tǒng)的支持
- Modules:不出意外,這個呼聲太高了。不但是編譯速度,就連最基礎(chǔ)的One Definition Rule的各種規(guī)則都能搞死人。最新的2篇modules提案:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4465.pdfhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4466.pdf說起來簡單,實現(xiàn)起來麻煩。目前提案者正在Visual C++中實現(xiàn)這些提案。因為這個呼聲很高,有理由相信進(jìn)入c++17的可能性很大。雖然目前進(jìn)展還不是很快的感覺??磒roposal目前還有一些小的design decision沒有明確下來,例如是否需要interface這個關(guān)鍵字之類的。
有了modules寫出來的代碼是什么樣子呢,大概是這個樣子,
import std.vector; import std.string; import std.iostream; import std.iterator;
怎樣寫module呢?
//abc.cpp (文件名無需和module名重合) module abc; struct internal { }; int internal_f() { } export namespace abc {class abc { }; }
注意C++的module僅僅只是編譯范疇的,并不是二進(jìn)制范疇的。效率為王。
- Modules:不出意外,這個呼聲太高了。不但是編譯速度,就連最基礎(chǔ)的One Definition Rule的各種規(guī)則都能搞死人。最新的2篇modules提案:
- Contracts:經(jīng)過11年被洗禮之后,這次加進(jìn)來問題應(yīng)該不大了。最新的提案:
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4415.pdf
出來時間比較久了,大家也都知道是干嘛的,也有劉雨培童鞋說過最新提案,我就不多說了,其實Contracts簡化后也是蠻復(fù)雜的,但基本上即使你從沒接觸過,讀懂別人寫的代碼的難度也不大。 - A type-safe union:也就是variant,基本上是在往functional-programming上靠。
Stroustrup桑還給了一個鏈接,13年他的一個學(xué)生(?)的論文,一個c++的pattern matching庫,蠻坑的。我覺得不進(jìn)行大改善,這個pattern matching庫進(jìn)入c++的標(biāo)準(zhǔn)可能性不大。
好奇的童鞋們不用找了,我拷個最簡單的例子出來。有了variant之后,這個match庫可以match類型+值。不過僅僅是庫而不是語言層面的支持,真是不倫不類啊。
int factorial(int n) {int m;Match(n) {Case (1) return 0;Case (m) return m*factorial(m-1);Case (_) throw std::invalid_argument(""); } EndMatch }
2. 關(guān)于并行
- 基礎(chǔ)網(wǎng)絡(luò)庫:這個太需要了,沒有基礎(chǔ)網(wǎng)絡(luò)庫,其他任何網(wǎng)絡(luò)相關(guān)的操作都是空中樓閣。
基于boost::asio的最新提案,
http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4478.html
boost::asio的async模型基本是callback。但這個proposal其實并不是簡單的boost::asio直接拷貝過來,除了基本的asio之外,還基于future和co-routine加了不少料。
例如,基于future的async模型,
std::future<std::size_t> fut =socket.async_read_some(buffer(buffer_space), use_future);// ...std::size_t length = fut.get(); 復(fù)雜一點還可以這樣,
socket.async_read_some(buffer(buffer_space), use_future).then([](std::size_t) {});
例如,基于co-routine的async模型(例子是stackful的,stackless需要語言層面支持)。
void coro_connection(tcp::socket& socket, yield_context yield) {try{std::vector<char> buffer_space(1024);for (;;){std::size_t length = socket.async_read_some(buffer(buffer_space), yield);uppercase(buffer_space.begin(), buffer_space.begin() + length);async_write(socket, buffer(buffer_space, length), yield);}}catch (std::system_error& e){// ...} } 基本上可以看出網(wǎng)絡(luò)庫是一個async模型的大雜燴,只要你有,我就支持。
最后,這個proposal還加了一些高級的庫(無需關(guān)注底層細(xì)節(jié))。
tcp::iostream s("www.boost.org", "http");s << "GET / HTTP/1.0\r\n"; s << "Host: www.boost.org\r\n"; s << "Accept: */*\r\n"; s << "Connection: close\r\n\r\n";std::string header; while (std::getline(s, header) && header != "\r")std::cout << header << "\n"; std::cout << s.rdbuf();
- 基礎(chǔ)網(wǎng)絡(luò)庫:這個太需要了,沒有基礎(chǔ)網(wǎng)絡(luò)庫,其他任何網(wǎng)絡(luò)相關(guān)的操作都是空中樓閣。
- SIMD vector:數(shù)學(xué)計算啊,游戲啊,沒什么好說的,研究這方面的自然懂,不研究的這個概念也沒啥復(fù)雜的。下面這個提案提出一個matrix 類,乘法等操作利用simd搞計算。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4492.pdf - Improved Future: 基本上都是微軟根據(jù).Net經(jīng)驗提出來的。就比如網(wǎng)絡(luò)庫的.then,就是基于此。你可以async_read( ).then().then().then(),等等。具體看proposal吧,蠻簡單易懂的。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3857.pdf - Co-routines:主體也是微軟搞出來的提案,基本和.net一樣的語法。在VC++上已經(jīng)有實現(xiàn)。本來這東西就分stackful還是stackless。微軟應(yīng)該是比較傾向于stackless的,google一人也提出了stackful和stackless的語法可以統(tǒng)一的一個提案。具體還未定。很可能是都支持,用戶可自由選擇的。其實微軟的提案還是比較吸引人。關(guān)鍵字:await,yield
https://isocpp.org/files/papers/N4402.pdf
我要多說一些,因為蠻有意思,
復(fù)制一下微軟的design goal:
* Highly scalable (to billions of concurrent coroutines)
* Highly efficient resume and suspend operations comparable in cost to a function call overhead
* Seamless interaction with existing facilities with no overhead
* Open ended coroutine machinery allowing library designers to develop coroutine libraries exposing various high-level semantics, such as generators, goroutines, tasks and more
* Usable in environments where exception are forbidden or not available
就看他的design goal就很想敢用了
寫出來的代碼什么樣子呢?await和yield關(guān)鍵字其實.net, python啊,java啊之類的也都有,沒什么好解釋的,要說下generator和goroutine,你沒看錯,是類Go語言的goroutine支持。
generator:
generator<int> fib(int n) {int a = 0;int b = 1;while (n-- > 0) {yield a;auto next = a + b;a = b;b = next;} } goroutine:
goroutine pusher(channel<int>& left, channel<int>& right) {for(;;) {auto val = await left.pull();await right.push(val + 1);} } int main() {static const int N = 1000 * 1000;std::vector<channel<int>> c(N + 1);for(int i = 0; i < N; ++i)goroutine::go(pusher(c[i], c[i + 1]));c.front().sync_push(0);std::cout << c.back().sync_pull() << std::endl; } - Trasactional Memory: 底部支持,沒什么好說的。基本是板上釘釘。
- Parallel STL
基本上就是并行實現(xiàn)的stl,可以選擇模式,例如sort
sort(begin(v), end(v)); //無并行 sort(seq, begin(v), end(v)); //無并行 sort(pal, begin(v), end(v)); //并行 sort(par_vec, begin(v), end(v)); //并行矢量化 execution_policy exec=seq; //動態(tài)決定 if (v.size() > 1000) exec = par; sort(exec, begin(v), end(v));
3. 語言用法簡化
- Concepts: 不說了
- Ranges: 也有童鞋說過了,不說了??傮w來說ranges就是一對數(shù)[i, j),或者一對iterator。需要對STL庫進(jìn)行添加支持針對Ranges的操作。例如你可以sort(v),而無需sort(begin(v), end(v))
- Default comparisons:就是說會自動生成operator >, ==之類的。對用戶自定義move或者copy的不會自動生成。
- Uniform call syntex:也有童鞋說過了。
目前這個提案大概是確認(rèn)了:如果f(x,y),那么就先找函數(shù),如果函數(shù)沒有,再找x.f(y)。而x.f(y)相反,找不到類x的f函數(shù),再去找 f(x,y)函數(shù)。也有另外一個選擇,就是x.f(y)和f(x,y)所有符合的全部放到一起然后做overloading resolution。這樣可能會破壞現(xiàn)有的代碼。還有2年時間可以討論選哪種。 - Operator dot: 沒什么可說的
- array_view和string_view: 蠻有意思的東西。
假設(shè)你有一個字符串“abcde, xyz",目前來說,如果你實現(xiàn)一個函數(shù),從逗號分割這個字符串,你會得到2個字符串"abcd", "xyz"。但如果有了string_view,你會得到2個string_view,每個string_view里面是一個(start, size)對,這樣就節(jié)省了多個字符串拷貝。
array_view可以更有意思,
auto M = 32; auto N = 64; auto v = vector<float>(M * N); auto av = array_view<float, 2>({M, N}, v); 你要問為啥不直接 vector<vector<float>>,因為這樣無法保證內(nèi)存連續(xù)分配啊。 - stack_array:還沒有proposal
- optional,和variant類似吧。目前沒有proposal,除非pattern matching被加到c++17中去了,否則不太可能17里實現(xiàn)。
以上就是stroustrup桑眼里的c++17應(yīng)該大概支持這些。當(dāng)然不是一個完整列表,不包括一些庫的改進(jìn)和語法小改進(jìn)。 不要想啦,C++ 17 毛都沒有。。。沒有 Module, 沒有 Coroutine, 沒有 Ranges,沒有 Reflection,沒有 Contracts,沒有……
唯一有希望的 Concepts 爭議很大。。也玄。
Network TS 也玄。
所以,……
--------------------------------------------------------------------------------------------------------------------------------
我的天,看到這個問題我激動得不知道說些什么好。在 BS 的那篇 Thoughts about C++ 17 里面已經(jīng)提到了很多提案了。我說一點我研究過的吧,算是拋磚引玉:
先說一些開胃菜吧。
- 模板的模板參數(shù)允許使用 typename(之前僅允許使用 class)
- 修改了 initializer_list 的推導(dǎo)原則:
For direct list-initialization:
1.For a braced-init-list with only a single element, auto deduction will deduce from that entry;
2.For a braced-init-list with more than one element, auto deduction will be ill-formed.
- 還解決了迷之 ill-formed/UB(這個詳細(xì)請自行閱讀http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4089.pdf)
- 嵌套的 namespace:
namespace A {namespace B { namespace C { //… } } }
- Fold Expressions:
- Concepts
&lt;img src="https://pic3.zhimg.com/9702ddd9a5ee7fd1e5fe91c003916fd2_b.png" data-rawheight="717" data-rawwidth="964" class="origin_image zh-lightbox-thumb" width="964" data-original="https://pic3.zhimg.com/9702ddd9a5ee7fd1e5fe91c003916fd2_r.png"&gt;注意!Sortable可不是Java/C#里的Interface,它叫做Concept。注意!Sortable可不是Java/C#里的Interface,它叫做Concept。
- Module
- Contracts
T& operator[](size_t i) [[expects: i < size()]]; ArrayView(const vector<T>& v) [[ensures: data() == v.data()]]; 那么不滿足這些conditions會發(fā)生什么呢?提案中說是“implemention-defined”。而且應(yīng)該允許每個TU獨立打開所有的測試,關(guān)閉所有,打開/關(guān)閉pre,打開關(guān)閉post。
- Unified Call Syntax
void f(FILE* file) { fseek(file,9,SEEK_SET); } //proposed new C++ code void f(FILE* file) { file->fseek(9,SEEK_SET); //nice autocomplete after "->" } 不過現(xiàn)在這個提案還有很多細(xì)節(jié)在商討。
說了一些我了解的Core Language特性,說一些庫的東西吧!先說點小東西
- std::invoke
template <class F, class Tuple, std::size_t... I> constexpr decltype(auto) apply_impl(F&& f, Tuple&& t, std::index_sequence<I...>) { return std::invoke(std::forward<F>(f), std::get<I>(std::forward<Tuple>(t))...); // Note: std::invoke is a C++17 feature } template <class F, class Tuple> constexpr decltype(auto) apply(F&& f, Tuple&& t) { return apply_impl(std::forward<F>(f), std::forward<Tuple>(t), std::make_index_sequence < std::tuple_size<std::decay_t<Tuple>>::value > {}); }
INVOKE的概念一直在標(biāo)準(zhǔn)里面,這回終于有了真正的invoke了。
- void_t
template<typename Iterator, typename = void> struct reference_type { using type = decltype(*declval<Iterator>()); // no reference, use operator* }; template<typename Iterator> struct reference_type<Iterator, void_t<typename Iterator::reference> > { using type = typename Iterator::reference; //I have a reference };
再說說大的。目前這些都屬于 TS 。
- 利用variable templates:
- filesystem
- network
- Ranges
Ranges!這個我必須說一說。我們經(jīng)常寫
std::sort(std::begin(v),std::end(v),std::greater<>{});那個begin end太煩了。Ranges就是為了解決這個問題:
std::sort(v,std::greater<>{});當(dāng)然遠(yuǎn)遠(yuǎn)不止這點,Ranges 里面的東西還可以花樣組合。你還可以寫出這樣的東西:
int total = accumulate(view::iota(1) | view::transform([](int x){return x*x;}) | view::take(10), 0); 其實背后的概念還是挺多的,例如 Iterable 等等。詳細(xì)的可以去看Ranges for the Standard Library, Revision 1 。- Type-erased Allocator
這個真的是深得我心啊!我最近正在按照目前的TS Draft實現(xiàn)這個東西。就是說一個vector:
std::vector<int,std::allocator<int>> v1; std::vector<int,MyAllocator<int>> v2; v1 = v2;//Error由于Allocator屬于類型的一部分,導(dǎo)致不同Allocator的vector不能copy啊等等。而且個人認(rèn)為std::allocator有點雞肋。這回好了,有了一個叫做memory_resource的抽象類:
class memory_resource {// For exposition onlystatic constexpr size_t max_align = alignof(max_align_t);public:virtual ~memory_resource();void* allocate(size_t bytes, size_t alignment = max_align);void deallocate(void* p, size_t bytes,size_t alignment = max_align);bool is_equal(const memory_resource& other) const noexcept;protected:virtual void* do_allocate(size_t bytes, size_t alignment) = 0;virtual void do_deallocate(void* p, size_t bytes,size_t alignment) = 0;virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; };之后有五種內(nèi)置的多態(tài)allocator:
- new_delete_resource(),使用::operator new/delete
- null_memory_resource(),使用allocate就會拋出std::bad_alloc
- synchronized_pool_resource
- unsynchronized_pool_resource
- monotonic_buffer_resource
有一個pmr::polymorphic_allocator的類滿足Allocator requirements,將一個memory_resource包裝起來:
#include <deque>namespace std { namespace experimental { inline namespace fundamentals_v2 { namespace pmr {template <class T>using deque = std::deque<T,polymorphic_allocator<T>>;} // namespace pmr } // namespace fundamentals_v2 } // namespace experimental } // namespace std#include <forward_list>namespace std { namespace experimental { inline namespace fundamentals_v2 { namespace pmr {template <class T>using forward_list =std::forward_list<T,polymorphic_allocator<T>>;} // namespace pmr } // namespace fundamentals_v2 } // namespace experimental } // namespace std當(dāng)然,我只是說了我了解的。還有很多其他的并發(fā)、并行算法、SIMD vector、string_view/array_view、optional/variant/any我沒有做深入了解,就不誤導(dǎo)大家了。
總結(jié)
- 上一篇: C#自定义特性实例
- 下一篇: spring boot启动加载tomca