2015-12-19 17 views
5

Bu işaretçi sarıcı (ham işaretçiyi değiştirerek) yaparak bu kodu this question'a yanıt olarak göndermeye çalışıyordum. Buradaki fikir, const'u pointee'ye atamaktır, böylece filter işlevi değerleri değiştiremez.g ++ ve clang ++ - aşırı yüklenmiş dönüşüm operatörü belirsizliği tarafından edinilen işaretçi silme

#include <iostream> 
#include <vector> 

template <typename T> 
class my_pointer 
{ 
    T *ptr_; 

public: 
    my_pointer(T *ptr = nullptr) : ptr_(ptr) {} 

    operator T* &()    { return ptr_; } 
    operator T const*() const { return ptr_; } 
}; 

std::vector<my_pointer<int>> filter(std::vector<my_pointer<int>> const& vec) 
{ 
    //*vec.front() = 5; // this is supposed to be an error by requirement 
    return {}; 
} 

int main() 
{ 
    std::vector<my_pointer<int>> vec = {new int(0)}; 
    filter(vec); 
    delete vec.front(); // ambiguity with g++ and clang++ 
} 

Visual C++ 12 ve 14 bir hata olmadan derleme bu ancak GCC ve bir belirsizlik olmaması Clang on Coliru iddia. Ben std::vector::front aşırı yüklenme ve my_pointer::operator T* &, ancak hayır. Nedenmiş?

+0

const aşırı yüklenmeyi geri döndürmeyi denemeye çalışın – bolov

+2

Temel olarak, standart derleyicinin neyin dönüştürüleceğine ilk karar vermesi gerektiğini ve sonra aşırı yük çözünürlüğünü çalıştırması gerektiğini söylüyor. Ama burada ilk adımda başarısız oluyor çünkü int * 've' const int * 'her ikisi de içeriğe izin veriyor. –

cevap

8

[expr.delete]/1:

işlenen türü veya sınıfı türü cisim işaretçi olacaktır. sınıf türünde, işlenen, bağlamsal olarak örtülü olarak dönüştürülür (madde [conv]), nesne türüne bir işaretçi dönüştürülür.

[dönüşüm]/5

, vurgu maden:

belirli dil yapıları oluşturmak için uygun tipleri, bir dizi özel bir sahip olan bir değere dönüşümü gerektirir. Sınıf türü bir sentezleme e böyle bir bağlamda ortaya Eiçeriğe dayalı örtülü ve e örtülü olan bir tür T dönüştürülebilir sadece eğer T ve iyi oluşturulur belirli bir tipine dönüştürülmüş olduğu söylenir E, cv T dönüş türü olmayan veya referansına göre, içerik tarafından izin verilmeyendönüşüm dışı arama için aranmıştır. Tam olarak gibi bir T olmalıdır. Kodunuzda

, iki tür T ler (int * ve const int *) vardır. Bu nedenle, aşırı yüklenmeye bile başlamadan önce, kötü biçimlendirilmiş durumda.


Bu alanda C++ 11 ve C++ 14 arasında bir değişiklik olduğunu unutmayın. C++ 11 [expr.delete]/1-2 işlenen türünü nesne için bir işaretçi, ya da tek bir açık olmayan dönüştürme işlevi (12.3.2) 'e sahip bir sınıf türü sahip olacaktır

der nesne türüne işaretçi . [...]

işlenen bir sınıf türü varsa, işlenen, yukarıda belirtilen dönüştürme fonksiyonunu çağırarak bir işaretçi türüne dönüştürülür [...]

okuma eğer hangi kelimenin tam anlamıyla, kodunuza izin verin ve her zaman operator const int*() const'u arayın, çünkü int* & nesne türü için bir işaretçi değil, bir referans türüdür. Uygulamada, uygulamalar dönüşüm işlevlerini operator int*&() gibi "nesne için işaretçiye başvurma" olarak değerlendirir ve ardından birden fazla niteleyici açık olmayan dönüşüm işlevine sahip olduğu için kodu reddeder.

+0

Sadece 'get' işlevini eklemeye çalıştım ve [çalıştım] (http://coliru.stacked-crooked.com/a/67adffa698e65623), bu yalnızca örtük dönüştürme işleçleriyle gerçekleşir mi? – LogicStuff

+1

@LogicStuff Doğru. Bir üye fonksiyonunu çağırmak sadece sıradan aşırı yük çözünürlüğü yapar ve eğer bir işaret döndürürse 'silme' mutludur. –

1

delete ifadesi, bir const ifadesini argüman olarak alır, bu const olabilir veya olmayabilir.

vec.front() const değil, ancak önce delete için bir işaretçiye dönüştürülmelidir. Yani her iki aday da const int* ve int* olası adaylar; derleyici, hangisini istediğinizi seçemez.

En ilgisi, seçimi çözümlemek için bir döküm kullanmaktır.

delete (int*)vec.front(); 

Remark: Örneğin kurallar farklıdır, çünkü bir dönüşüm yerine get() işlevini kullandığınızda çalışıyor. Aşırı yüklenen fonksiyonun seçimi, dönüş türünde değil, parametrelerin tipi ve nesneye dayanır. Burada const olmayan best viable işlevi olarak vec.front() const değil.

+1

Bunun tam bir yanıt olduğunu düşünmüyorum çünkü derleyici normal işlev çağrıları için const olmayan nesneler için her zaman const olmayan işlevlerini seçer. Bu durumda hiçbir belirsizlik yoktur, bu yüzden neden bu durumda olmalı? – Kevin

İlgili konular