Di C ++ 11, using
kata kunci saat digunakan untuk type alias
identik dengan typedef
.
7.1.3.2
Nama typedef juga bisa dimasukkan dengan deklarasi alias. Pengenal yang mengikuti kata kunci yang digunakan menjadi nama-typedef dan atribut-penentu-seq opsional yang mengikuti pengenal yang ada pada nama-typedef itu. Ini memiliki semantik yang sama seolah-olah itu diperkenalkan oleh penentu typedef. Secara khusus, ini tidak mendefinisikan tipe baru dan tidak akan muncul di tipe-id.
Bjarne Stroustrup memberikan contoh praktis:
typedef void (*PFD)(double);
using PF = void (*)(double);
using P = [](double)->void;
using P = auto(double)->void
Sebelum C ++ 11, using
kata kunci dapat membawa fungsi anggota ke dalam cakupan. Di C ++ 11, Anda sekarang dapat melakukan ini untuk konstruktor (contoh Bjarne Stroustrup lainnya):
class Derived : public Base {
public:
using Base::f;
void f(char);
void f(int);
using Base::Base;
Derived(char);
Derived(int);
};
Ben Voight memberikan alasan yang cukup bagus di balik alasan tidak memperkenalkan kata kunci baru atau sintaks baru. Standar ingin menghindari kerusakan kode lama sebanyak mungkin. Inilah sebabnya mengapa dalam dokumen usulan Anda akan melihat bagian seperti Impact on the Standard
, Design decisions
, dan bagaimana mereka dapat mempengaruhi kode yang lebih tua. Ada situasi ketika sebuah proposal tampak seperti ide yang sangat bagus tetapi mungkin tidak memiliki daya tarik karena akan terlalu sulit untuk diterapkan, terlalu membingungkan, atau akan bertentangan dengan kode lama.
Ini adalah kertas tua dari tahun 2003 n1449 . Alasannya tampaknya terkait dengan template. Peringatan: mungkin ada kesalahan ketik karena menyalin dari PDF.
Pertama mari kita pertimbangkan contoh mainan:
template <typename T>
class MyAlloc {};
template <typename T, class A>
class MyVector {};
template <typename T>
struct Vec {
typedef MyVector<T, MyAlloc<T> > type;
};
Vec<int>::type p;
Masalah mendasar dengan idiom ini, dan fakta motivasi utama untuk proposal ini, adalah bahwa idiom tersebut menyebabkan parameter template muncul dalam konteks yang tidak dapat disimpulkan. Artinya, tidak mungkin memanggil fungsi foo di bawah ini tanpa menentukan argumen template secara eksplisit.
template <typename T> void foo (Vec<T>::type&);
Jadi, sintaksnya agak jelek. Kami lebih suka menghindari bersarang. ::type
Kami lebih suka sesuatu seperti berikut ini:
template <typename T>
using Vec = MyVector<T, MyAlloc<T> >;
Vec<int> p;
Perhatikan bahwa kami secara khusus menghindari istilah "template typedef" dan memperkenalkan sintaks baru yang melibatkan pasangan "menggunakan" dan "=" untuk membantu menghindari kebingungan: kami tidak mendefinisikan tipe apa pun di sini, kami memperkenalkan sinonim (yaitu alias) untuk sebuah abstraksi dari tipe-id (yaitu ekspresi tipe) yang melibatkan parameter template. Jika parameter template digunakan dalam konteks deducible dalam ekspresi tipe maka setiap kali alias template digunakan untuk membentuk template-id, nilai parameter template terkait dapat disimpulkan - lebih lanjut akan mengikuti. Dalam kasus apapun, sekarang dimungkinkan untuk menulis fungsi generik yang beroperasi Vec<T>
dalam konteks deducible, dan sintaksnya juga ditingkatkan. Misalnya kita bisa menulis ulang foo sebagai:
template <typename T> void foo (Vec<T>&);
Kami menggarisbawahi di sini bahwa salah satu alasan utama untuk mengusulkan alias template adalah agar pengurangan argumen dan panggilan ke foo(p)
akan berhasil.
Makalah tindak lanjut n1489 menjelaskan mengapa using
alih - alih menggunakan typedef
:
Telah disarankan untuk menggunakan (kembali) kata kunci typedef - seperti yang dilakukan di makalah [4] - untuk memperkenalkan alias template:
template<class T>
typedef std::vector<T, MyAllocator<T> > Vec;
Notasi itu memiliki keuntungan menggunakan kata kunci yang sudah dikenal untuk memperkenalkan alias tipe. Namun, ini juga menampilkan beberapa kekurangan di antaranya kebingungan dalam menggunakan kata kunci yang dikenal untuk memperkenalkan alias untuk nama-tipe dalam konteks di mana alias tidak menunjuk pada suatu tipe, melainkan templat; Vec
bukan sebuah alias untuk suatu tipe, dan tidak boleh diambil untuk nama-typedef. Nama Vec
adalah nama untuk keluarga std::vector< [bullet] , MyAllocator< [bullet] > >
- di mana poin adalah tempat penampung untuk nama tipe. Akibatnya kami tidak mengusulkan sintaks "typedef". Di sisi lain kalimat tersebut
template<class T>
using Vec = std::vector<T, MyAllocator<T> >;
dapat dibaca / diartikan sebagai: mulai sekarang, saya akan menggunakan Vec<T>
sebagai sinonim untuk std::vector<T, MyAllocator<T> >
. Dengan pembacaan itu, sintaks baru untuk aliasing tampaknya masuk akal.
Saya pikir perbedaan penting dibuat di sini, alias es alih-alih tipe s. Kutipan lain dari dokumen yang sama:
Sebuah alias-deklarasi adalah sebuah deklarasi, dan bukan sebuah definisi. Sebuah alias- deklarasi memperkenalkan nama ke dalam kawasan deklaratif sebagai alias untuk tipe yang ditunjuk oleh sisi kanan deklarasi. Inti dari proposal ini berkaitan dengan alias nama tipe, tetapi notasi jelas dapat digeneralisasikan untuk memberikan ejaan alternatif dari namespace-aliasing atau set penamaan fungsi yang kelebihan beban (lihat ✁ 2.3 untuk diskusi lebih lanjut). [ Catatan saya: Bagian itu membahas seperti apa tampilan sintaks itu dan alasan mengapa itu bukan bagian dari proposal. ] Perlu dicatat bahwa deklarasi-alias produksi tata bahasa dapat diterima di mana pun deklarasi typedef atau definisi-alias-ruang nama dapat diterima.
Ringkasan, untuk peran using
:
- alias template (atau template typedefs, nama sebelumnya lebih disukai)
- alias namespace (yaitu,
namespace PO = boost::program_options
dan using PO = ...
setara)
- kata dokumen itu
A typedef declaration can be viewed as a special case of non-template alias-declaration
. Ini adalah perubahan estetika, dan dianggap identik dalam kasus ini.
- membawa sesuatu ke dalam ruang lingkup (misalnya,
namespace std
ke dalam lingkup global), fungsi anggota, mewarisi konstruktor
Ini tidak dapat digunakan untuk:
int i;
using r = i;
Sebaliknya lakukan:
using r = decltype(i);
Memberi nama sekumpulan kelebihan beban.
using std::cos;
using std::cos(double);
using test = std::cos(double);