int numeral -> işaretçi dönüştürme kuralları


19

Aşağıdaki kodu düşünün.

void f(double p) {}
void f(double* p) {}

int main()
{ f(1-1); return 0; }

MSVC 2017 bunu derlemiyor. Aynı şekilde 1-1olduğu gibi belirsiz bir aşırı yüklenmiş çağrı olduğunu 0ve bu nedenle dönüştürülebileceğini gösterir double*. Diğer hileler gibi 0x0, 0Lya static_cast<int>(0), ya çalışmaz. Bir const int Zero = 0ve bildirimi bile f(Zero)aynı hatayı üretir. Sadece düzgün çalıştığını Zerodeğildir const.

Aynı sorun GCC 5 ve altı için de geçerli, ancak GCC 6 için geçerli değil. Bunun C ++ standardının bir parçası, bilinen bir MSVC hatası veya derleyicideki bir ayar olup olmadığını merak ediyorum. Bir cursory Google sonuç vermedi.

Yanıtlar:


18

MSVC 1-1, boş bir işaretçi sabiti olarak kabul edilir. Bu, değeri olan tüm integral sabit ifadelerin 0boş işaretçi sabitleri olduğu C ++ 03 standardı için doğruydu , ancak CWG sorunu 903 ile C ++ 11 için sadece sıfır tamsayı değişmezi boş işaretçi sabitleri olacak şekilde değiştirildi . Bu, örneğinizde de görebileceğiniz gibi ve standartta da belgelendiği gibi, bir kırılma değişikliğidir, bkz. C ++ 14 standardının [diff.cpp03.conv] (taslak N4140).

MSVC bu değişikliği yalnızca uyumluluk modunda uygular. Kodunuz /permissive-bayrakla derlenecek , ancak değişikliğin sadece MSVC 2019'da uygulandığını düşünüyorum, buraya bakın .

GCC durumunda, GCC 5 varsayılan olarak C ++ 98 moduna geçerken GCC 6 ve üstü varsayılan olarak C ++ 14 moduna geçer, bu nedenle davranış değişikliği GCC sürümüne bağlı gibi görünmektedir.

Değişken folarak bir boş işaretçi sabiti ile çağırırsanız, çağrı belirsizdir, çünkü boş işaretçi sabiti herhangi bir işaretçi türünde boş bir işaretçi değerine dönüştürülebilir ve bu dönüşüm, dönüşümle int(veya tümleşik bir türle) aynı sıralamaya sahiptir. için double.


-1

Derleyici, [over.match] ve [conv] , daha spesifik olarak [conv.fpint] ve [conv.ptr] 'e göre düzgün çalışır .

Standart bir dönüşüm sırası [blah blah] Sıfır veya bir [...] kayan integral dönüşümleri, işaretçi dönüşümleri, [...].

ve

Bir tamsayı türünün veya kodlanmamış numaralandırma türünün bir ön değeri, bir kayan nokta türünün bir ön değerine dönüştürülebilir. Mümkünse sonuç kesindir [falan filan]

ve

Boş gösterici sabiti, sıfır veya [...] değerine sahip bir tam sayı değişmezidir. Bir boş işaretçi sabiti bir işaretçi türüne dönüştürülebilir; sonuç, bu türdeki boş gösterici değeridir [blah blah]

Şimdi, aşırı yük çözünürlüğü tüm aday işlevler arasında en iyi eşleşmeyi seçmektir (eğlenceli bir özellik olarak çağrı konumunda bile erişilebilir olması gerekmez!). En iyi eşleşme, tam parametreleri olan veya alternatif olarak mümkün olan en az dönüşüm olanıdır. Sıfır veya bir standart dönüşüm olabilir (... her parametre için) ve sıfır birinden "daha iyidir".

(1-1)değeri olan bir tam sayı değişmezidir 0.

Sıfır tamsayısını tam olarak bir dönüşümle ya da (veya ) her birine dönüştürebilirsiniz. Bu nedenle, bu işlevlerden birden fazlasının (örnekteki gibi) beyan edildiği varsayıldığında, tek bir adaydan daha fazlası vardır ve tüm adaylar eşit derecede iyidir, en iyi eşleşme yoktur. Bu belirsiz ve derleyici şikayet konusunda haklı.doubledouble*nullptr_t


1
Nasıl 1-1bir tamsayı değişmezi ? Değerli iki tamsayı değişmez değeri 1ve bir -işleç içeren bir ifadedir .
Ceviz

@walnut: Muhtemelen "ikili rakamlar, sekizli rakamlar, rakamlar veya onaltılık rakamlar" dizisinin garip ifadelerine atıfta bulunuyorsunuz . Bu oldukça "açık" bir şey için çok şanssız bir şekilde ifade edilir, bu durum böyle olmayan bir şey önerir (yani eksi karakteri hariç tutmak). Sadece "rakamlar" ile ve "rakam" tanımına (0 ... 9'dan biri) göre bilgiçlikle, herhangi bir negatif değişmeze (örneğin -1) sahip olmak mümkün değildir . Bununla birlikte, varsayılan tip imzalandığı için açık bir şekilde gereklidir ve bu da açıkça mümkündür (ve evrensel olarak kabul edilir).
Damon

1
Eşleşmeyen standart bağlantıda gösterilen tamsayı-literal için gramerden bahsediyorum 1-1. C ++ negatif tamsayı değişmezine sahip değil. -1bir 1tam sayı değişmezinden (işaretli türden) ve -tekli eksi operatörden oluşan bir ifadedir . Ayrıca, cppreference.com adresindeki "Notlar" bölümüne bakın .
Ceviz

Dilbilgisinin buna sahip olmadığı kesinlikle doğrudur, ancak bu büyük ölçüde önemsizdir. Elzem ve tanımı gereği, C ++ çok var açıkça ekleme sürece bu yana, olumsuz değişmezleri u, senin gerçek olmalıdır, tanım başına imzaladı. Kayıtlı türleri var negatif değerler (olası değerler yaklaşık% 50'si negatif). Dilbilgisinin (bilmediğim bir nedenden dolayı) bu şekilde yanıltıcı olması talihsiz bir durumdur ve teknik olarak (dilbilgisine göre) -1 olumlu bir değişmez, olumsuz, elbette negatiftir. değişmezi. 3 + 4'e çok benzer.
Damon

Bu arada - denedim 0U. Aynı sorun. Ben denemedim bir enumdeğerdir. Belki de isimlendirilmiş biri bazı şeyleri değiştirebilirdi. Ben uzun ifadeyi yazma sona erdi decltypeve remove_reference.
user1334767
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.