Bir şeyi "ODR-kullanmak" ne anlama geliyor?


92

Bu, başka bir soru bağlamında ortaya çıktı .

Görünüşe göre sınıf şablonlarındaki üye işlevler yalnızca ODR kullanılıyorsa somutlaştırılır. Biri bunun tam olarak ne anlama geldiğini açıklayabilir mi? Bir Tanım Kuralı (ODR) üzerinde wikipedia makale "söz etmez ODR kullanımını ".

Ancak standart bunu şu şekilde tanımlar:

Adı potansiyel olarak değerlendirilmiş bir ifade olarak görünen bir değişken, sabit bir ifadede (5.19) görünme gereksinimlerini karşılayan bir nesne olmadığı sürece odr kullanılır ve ldeğerden r değerine dönüştürme (4.1) hemen uygulanır.

[basic.def.odr] içinde.

Düzenleme: Görünüşe göre bu yanlış kısım ve paragrafın tamamı farklı şeyler için birden fazla tanım içeriyor. Bu, sınıf şablonu üye işlevi için uygun olabilir:

Adı potansiyel olarak değerlendirilmiş bir ifade veya potansiyel olarak değerlendirilmiş bir ifadeden atıfta bulunulduğunda aşırı yük çözümlemesi ile seçilirse, adı potansiyel olarak değerlendirilmiş bir ifade veya bir aday işlevler kümesinin üyesi olarak görünen aşırı yüklenmemiş bir işlev, tamamen sanal olmadığı sürece odr kullanılır. işlev ve adı açıkça nitelenmemiş.

Bununla birlikte, bu kuralın birden çok derleme biriminde nasıl çalıştığını anlamıyorum? Açıkça bir sınıf şablonu başlatırsam tüm üye işlevler başlatılır mı?


2
[Basic.def.odr] / 6'nın sınıf şablonlarının üye işlevleri için geçerli olduğuna dikkat edin "Birden fazla tanım olabilir [...]"
dyp

3
"Açıkça bir sınıf şablonunu başlatırsam tüm üye işlevler başlatılır mı?" Evet, bkz. [Temp.explicit] / 8 + 9
dyp

Yanıtlar:


71

Bu, standart tarafından bir varlık için ne zaman bir tanım sağlamanız gerektiğini belirtmek için kullanılan keyfi bir tanımdır (yalnızca bir bildirimin aksine). Standart sadece "kullanılmış" demiyor, çünkü bu, bağlama göre farklı şekillerde yorumlanabilir. Ve bazı ODR kullanımları, normalde "kullanım" ile ilişkilendirilecek olana tam anlamıyla karşılık gelmez; örneğin, bir sanal işlev, programın herhangi bir yerinde çağrılmasa bile, saf olmadığı sürece her zaman ODR kullanılır.

Tam tanım §3.2 , ikinci paragrafta yer almaktadır, ancak bu, tanımı tamamlamak için diğer bölümlere atıflar içermektedir.

Şablonlarla ilgili olarak, ODR kullanımı söz konusu yalnızca bir kısmıdır; diğer kısım ise somutlaştırmadır. Özellikle, §14.7 bir şablonun ne zaman somutlaştırıldığını kapsar. Ancak ikisi birbiriyle ilişkilidir: §14.7.1'deki (örtük somutlaştırma) metin oldukça uzun olsa da, temel ilke, bir şablonun yalnızca kullanılması durumunda somutlaştırılacağıdır ve bu bağlamda, ODR kullanılan anlamına gelir. Bu nedenle, bir sınıf şablonunun üye işlevi yalnızca çağrılırsa veya sanalsa ve sınıfın kendisi başlatılırsa somutlaştırılır. Birçok yerde bu konuda kendisi sayan, standart: std::list<>::sortkullanımları <bağımsız öğelerin ama desteklemeyen bir eleman türü üzerinden bir liste örneğini <sürece demiyorlar gibi sortüzerinde.


ODR kullanımı "maddileşmiş geçiciler" ile örtüşebilir mi?
v.oddou

23

Basit bir deyişle, kullanılan odr, tanımının mevcut olması gereken bir bağlamda kullanılan bir şey (değişken veya işlev) anlamına gelir.

Örneğin,

struct F {
   static const int g_x = 2;
};

int g_x_plus_1 = F::g_x + 1; // in this context, only the value of g_x is needed.
                             // so it's OK without the definition of g_x

vector<int>  vi;
vi.push_back( F::g_x );      // Error, this is odr-used, push_back(const int & t) expect
                             // a const lvalue, so it's definition must be present

Yukarıdaki geri itme MSVC 2013'te geçti, bu davranış standart uyumluluk değil, hem gcc 4.8.2 hem de clang 3.8.0 başarısız oldu, hata mesajı: K :: g_x'e tanımsız başvuru


vi.push_back( F::g_x );C ++ 'da olduğu gibi statik bir veri üyesini odr-kullanmak mümkün müdür ?
Rankaba

Ancak bir r değeri de aktarılabilir const int&mi? Statik const üyesi rvalue olarak sınıflandırılabilir mi?
scottxiao

8
Kısa ve öz açılış cümlesi için +1: "Basit bir ifadeyle, odr-used, tanımının mevcut olması gereken bir bağlamda kullanılan bir şey (değişken veya işlev) anlamına gelir."
Paul Masri-Stone

1
Bu kodu nasıl derlediğini anlamıyorum. Aynı derslikte mi? Öyleyse, F :: g_x zaten önceden tanımlanmıştır push_back, elbette geçecektir. Değil mi?
Lewis Chan

1
@bigxiao " bir rvalue da iletilebilir " Evet ve derleyici tarafından geçici bir nesne oluşturulur ve referans o nesneye bağlanır. OTOH, bir l değeri geçerken, bu, ldeğerin değerlendirilmesiyle başvurulan nesneyi iletmek anlamına gelir: bir l değeri ilettiğinizde, işlevdeki parametrenin doğru nesneye başvurmasını bekleyebilirsiniz. Derleyici bir geçici oluşturmayacaktır. Geçici bir şey istiyorsanız, bir tane yapın operator+.
wonderguy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.