總覽
using
比typedef
好在哪些地方.
using
支持模板的別名.
using
有編譯器加持.相同點
都是別名,不過
using
的看起來更加簡潔.
相同點
別名
#include<iostream> using Myshow = void (*)(); typedef void(*Dshow)(); void show() { std::cout << __LINE__ << std::endl; } int main() { Myshow{&show}(); Dshow{&show}(); // 二義性,優先定義,而非初始化. // Dshow(&show)(); }
都挺簡單,但是
typedef
的有點略難懂.
模板別名
using
#include<iostream> #include<vector> template<typename T> using Myvector = std::vector<T>; int main() { Myvector<int> b{1,2,3}; for(const auto& a : b) { std::cout << a << std::endl; } }
正常編譯執行
typedef
模仿#include<iostream> #include<vector> template<typename T> typedef std::vector<T> Myvector; int main() { Myvector<int> b{1,2,3}; for(const auto& a : b) { std::cout << a << std::endl; } }
編譯報錯
改改
typedef
#include<iostream> #include<vector> template<typename T> struct Myvector { typedef std::vector<T> type; }; int main() { Myvector<int>::type b{1,2,3}; for(const auto& a : b) { std::cout << a << std::endl; } }
勉強可以用,但是不夠簡潔了呀.
別名類型做成員變量
using
#include<iostream> #include<vector> template<typename T> using Myvector = std::vector<T>; template<typename T> class Temp { public: Myvector<T> a; }; int main() { Temp<int> b{{1,2,3}}; for(const auto& a : b.a) { std::cout << a << std::endl; } }
正常輸出
123
.
typedef
#include<iostream> #include<vector> template<typename T> typedef std::vector<T> Myvector; template<typename T> class Temp { public: Myvector<T> a; }; int main() { Temp<int> b{{1,2,3}}; for(const auto& a : b.a) { std::cout << a << std::endl; } }
這種肯定編不過.上面都編不過。
typedef
改改版#include<iostream> #include<vector> template<typename T> struct Myvector { typedef std::vector<T> type; }; template<typename T> class Temp { public: Myvector<T>::type a; }; int main() { Temp<int> b{{1,2,3}}; for(const auto& a : b.a) { std::cout << a << std::endl; } }
用上面的改一改,加內置了,編譯報錯.
因爲不知道
type
是類型還是變量名.無法預測未來.可行版
typedef
#include<iostream> #include<vector> template<typename T> struct Myvector { typedef std::vector<T> type; }; template<typename T> class Temp { public: typename Myvector<T>::type a; }; int main() { Temp<int> b{{1,2,3}}; for(const auto& a : b.a) { std::cout << a << std::endl; } }
這種是可行的,但是看起來好麻煩.
必須通過關鍵字
typename
告訴編譯器Myvector<T>::type
是一個類型而不是變量.小結
typedef
在c++11
沒有辦法完美的適應環境了.間接類型需要用
typename
聲明其是類型不是變量名.編譯器笨吧.
using
命名後的就不需要也不允許typename
的出現了.小疑問
Myvector<T>::type
如果是類型,Myvector<T>::type()
就是匿名對象創建,調用默認構造.或者是函數聲明?Myvector<T>::type
如果是變量名,恰好是個可調用對象,那麼就是匿名返回值. 無法解析.語義都不一樣了.
爲什麼不增強typedef
的功能
開發就需要做到,不改原來的基礎上增加新的功能. 開閉原則.
C++
標準庫的實現
type_traits
主要是用在元模板編程了.
可以通過傳入類型然後返回這個類型的另外的類型,比如加減修飾.
const
類型獲取對應的非const
類型.&
類型獲取到對應的非引用類型.獲取某個類型的普通版本變量
#include <iostream> #include <type_traits> int main() { const int a = 0; std::remove_const<decltype(a)>::type b; b = 1; return 0; }
得到這個變量的普通版本.
不太好看,每次都要加一個
::type
.
using
版本#include <iostream> #include <type_traits> template <typename T> using remove_const_t = typename std::remove_const<T>::type; int main() { const int a = 0; remove_const_t<decltype(a)> b; b = 1; return 0; }
typedef
無法支持,只能在內部類中創建.
type_traits
c++11
使用的typedef
在內部實現的這種機制.
c++14
的時候才採用typedef
的方式實現.remove_const_t
的形式. 如上.
總結
using
在模板別名方面表現比typedef
好.
using
有編譯器加持.間接名需要用
typename
而typedef
不需要.