C ++ 11'de, using
kullanıldığında anahtar sözcük type alias
aynıdır typedef
.
7.1.3.2
Bir typedef-name, bir takma ad bildirimi ile de eklenebilir. Using anahtar sözcüğünü izleyen tanımlayıcı, typedef-name olur ve tanımlayıcıyı izleyen isteğe bağlı attribute-specifier-seq, bu typedef-name için görünür. Typedef belirleyicisi tarafından tanıtılmış gibi aynı anlambilime sahiptir. Özellikle, yeni bir tür tanımlamaz ve tür kimliğinde görünmez.
Bjarne Stroustrup pratik bir örnek sunmaktadır:
typedef void (*PFD)(double); // C style typedef to make `PFD` a pointer to a function returning void and accepting double
using PF = void (*)(double); // `using`-based equivalent of the typedef above
using P = [](double)->void; // using plus suffix return type, syntax error
using P = auto(double)->void // Fixed thanks to DyP
C ++ 11 öncesi, using
anahtar kelime üye işlevlerini kapsama alabilir. C ++ 11'de artık bunu yapıcılar için yapabilirsiniz (başka bir Bjarne Stroustrup örneği):
class Derived : public Base {
public:
using Base::f; // lift Base's f into Derived's scope -- works in C++98
void f(char); // provide a new f
void f(int); // prefer this f to Base::f(int)
using Base::Base; // lift Base constructors Derived's scope -- C++11 only
Derived(char); // provide a new constructor
Derived(int); // prefer this constructor to Base::Base(int)
// ...
};
Ben Voight, yeni bir anahtar kelime veya yeni sözdizimi sunmamanın mantığının arkasında oldukça iyi bir neden sunuyor. Standart, eski kodu olabildiğince kırmaktan kaçınmak istiyor. Bu nedenle, teklif belgelerinde Impact on the Standard
, gibi bölümleri Design decisions
ve bunların eski kodu nasıl etkileyebileceğini göreceksiniz . Bir teklifin gerçekten iyi bir fikir gibi göründüğü, ancak çekilmeyebileceği durumlar vardır, çünkü uygulanması çok zor, kafa karıştırıcı veya eski kodla çelişecektir.
İşte 2003 n1449 eski bir makale . Gerekçe şablonlarla ilgili görünmektedir. Uyarı: PDF'den kopyalama nedeniyle yazım hataları olabilir.
İlk olarak bir oyuncak örneği düşünelim:
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; // sample usage
Bu deyimle ilgili temel sorun ve bu teklif için temel motive edici gerçek, deyimin şablon parametrelerinin çıkartılamaz bağlamda görünmesine neden olmasıdır. Yani, şablon argümanlarını açıkça belirtmeden aşağıdaki foo işlevini çağırmak mümkün olmayacaktır.
template <typename T> void foo (Vec<T>::type&);
Yani sözdizimi biraz çirkin. Yuvadan kaçınmayı ::type
tercih ederiz Aşağıdaki gibi bir şeyi tercih ederiz:
template <typename T>
using Vec = MyVector<T, MyAlloc<T> >; //defined in section 2 below
Vec<int> p; // sample usage
“Typedef template” teriminden özellikle kaçındığımızı ve karışıklığı önlemek için “using” ve “=” çiftini içeren yeni sözdizimini ürettiğimizi unutmayın: burada herhangi bir tür tanımlamıyoruz, bunun için bir eşanlamlı (diğer ad) sunuyoruz. şablon parametrelerini içeren bir tip kimliğinin (yani, tür ifadesi) soyutlanması. Şablon parametreleri tür ifadesinde çıkarılabilir bağlamlarda kullanılıyorsa, şablon takma adı bir şablon kimliği oluşturmak için her kullanıldığında, karşılık gelen şablon parametrelerinin değerleri çıkarılabilir - bunu daha fazlası takip edecektir. Her durumda, artık çıkartılabilir Vec<T>
bağlamda çalışan genel işlevler yazmak mümkündür ve sözdizimi de geliştirilir. Örneğin foo'yu şu şekilde yeniden yazabiliriz:
template <typename T> void foo (Vec<T>&);
Burada, şablon takma adları önermenin temel nedenlerinden birinin, argüman çıkarımının ve çağrının foo(p)
başarılı olacağının altını çiziyoruz.
Takip belgesi n1489 neden using
kullanmak yerine açıklamaktadır typedef
:
Şablon takma adlarını tanıtmak için [4] yazısında olduğu gibi typedef anahtar kelimesinin (yeniden) kullanılması önerilmiştir:
template<class T>
typedef std::vector<T, MyAllocator<T> > Vec;
Bu gösterim, bir tür takma adı tanıttığı bilinen bir anahtar kelimeyi kullanma avantajına sahiptir. Bununla birlikte, takma adın bir tür değil, bir şablon belirttiği bir bağlamda bir tür adı için bir diğer ad tanıtmak için bilinen bir anahtar sözcüğü kullanmanın karışıklığı da vardır. Vec
bir türün takma adı değildir ve typedef-name için alınmamalıdır. Ad Vec
, ailenin bir adıdır std::vector< [bullet] , MyAllocator< [bullet] > >
- burada madde işareti bir tür adı için yer tutucudur. Sonuç olarak “typedef” sözdizimini önermiyoruz. Öte yandan cümle
template<class T>
using Vec = std::vector<T, MyAllocator<T> >;
şu şekilde okunabilir / yorumlanabilir: şu andan itibaren, Vec<T>
eşanlamlı olarak kullanacağım std::vector<T, MyAllocator<T> >
. Bu okuma ile, takma ad için yeni sözdizimi oldukça mantıklı görünüyor.
Bence burada önemli bir ayrım yapılmış, s türü yerine takma adlar var . Aynı belgeden başka bir alıntı:
Takma ad bildirimi bir tanım değildir, bir tanımdır. Bir takma ad, deklarasyonun sağ tarafının belirlediği tür için bir takma ad olarak deklaratif bir bölgeye bir ad verir. Bu teklifin özü, tür adı takma adlarıyla ilgilidir, ancak gösterim, ad alanı örtüşmesinin veya aşırı yüklenmiş işlevlerin adlandırılmasının alternatif yazımlarını sağlamak için açıkça genelleştirilebilir (daha fazla tartışma için ✁ 2.3'e bakın). [ Notum: Bu bölüm söz diziminin nasıl görünebileceğini ve teklifin bir parçası olmamasının nedenlerini tartışıyor. ] Dilbilgisi üretim takma adı bildiriminin bir typedef bildirimi veya bir ad-alanı takma adı tanımının kabul edilebilir olduğu her yerde kabul edilebilir.
Özet, rolü için using
:
- şablon takma adları (veya şablon typedefs, eski ad tercih edilir)
- ad alanı takma adları (ör.
namespace PO = boost::program_options
ve using PO = ...
eşdeğeri)
- belge diyor
A typedef declaration can be viewed as a special case of non-template alias-declaration
. Bu estetik bir değişikliktir ve bu durumda aynı kabul edilir.
- bir şeyi kapsama getirmek (örneğin,
namespace std
küresel kapsama), üye işlevleri, kurucuları devralma
O olamaz için kullanılabilir:
int i;
using r = i; // compile-error
Bunun yerine şunları yapın:
using r = decltype(i);
Bir dizi aşırı yükü adlandırmak.
// bring cos into scope
using std::cos;
// invalid syntax
using std::cos(double);
// not allowed, instead use Bjarne Stroustrup function pointer alias example
using test = std::cos(double);