SORU
19 Aralık 2014, Cuma


Kısmi işlev şablonları sipariş - belirsiz Ara

Bu C 11 kod parçası göz önünde bulundurun:

#include <iostream>
#include <cstddef>

template<typename T> void f(T, const char*) //#1
{ 
    std::cout << "f(T, const char*)\n"; 
}

template<std::size_t N> void f(int, const char(&)[N]) //#2
{ 
    std::cout << "f(int, const char (&)[N])\n"; 
}

int main()
{
    f(7, "ab");
}

Tamam, Peki... hangi aşırı seçilir? Derleyici çıktısı ile atacaksınız önce, bu konuyu neden çalışın.

(Bölüm tüm başvurular için son standart belge için C 11, ISO/IEC 14882:2011.)

T#1. int, N çıkarılabilir#23 için birebir hem uzmanlıklar adayların, her iki canlı vardır, şimdiye kadar çok iyi. Hangisi daha iyi olur?

İlk olarak, örtülü dönüşüm işlev parametreleri işlev bağımsız değişkenlerini maç için gerekli olarak kabul edilir. İlk argümanı olarak, herhangi bir dönüştürme her iki durumda da gereklidir (kimlik dönüşüm), int her yerde, bu yüzden iki işlevi de aynı derecede iyi. İkincisi için, bağımsız değişken türü ** 14, ve iki, bu hadise

  • için#1,dizi için işaretçi dönüşümkategorilvalue dönüşüm, [13.3.3.1.1]; bu dönüşüm kategorisi bu temelde aynı olduğu için, [13.3.3.2] göre dönüşüm dizileri karşılaştırırken göz ardı edilir görekimlik dönüşümbu amaçla;
  • için#2başvuru türü parametresi ve doğrudan tartışma, bu yüzden, [13.3.3.1.4] göre bu tekrar bağlanırkimlik dönüşüm.

Yine şans yok: iki işlevi hala eşit derecede iyi. Hem şablon uzmanlık olmak, artık işlev şablonu varsa, görmek içindaha özel([14.5.6.2] [14.8.2.4]).

EDİT 3: aşağıdaki açıklama yakın, ama tam doğru değil. İşlemi doğru bir açıklaması olduğuna inandığım için benim cevaba bakınız.

  • İle tartışma indirimi şablon#1parametre olarak#2argüman olarak: biz icat bir değer M tedavi için N, T çıkarılabilir int, const char* parametre olabilir başlatılmamış bir değişken tipi char[M], Her şey yolunda. Söyleyebileceğim kadarıyla#2en az olarak kurulmuştur#1her türlü yer.
  • İle tartışma indirimi şablon#2parametre olarak#1argüman olarak: biz icat bir tür U yerine T bir parametre türü int olamaz başlatılmamış bir değişken tipi U (alakasız tipleri), bir parametre türü char[N] olamaz başlatılmamış bir değişken tipi const char* ve değeri olmayan bir tür parametresi N olamaz sonucuna bağımsız değişkenler, bu yüzden... her şey başarısız olur. Söyleyebileceğim kadarıyla#1en azından uzman olarak değil#2her türlü yer.

EDİT 1: yukarıdaki başvurular bu durumda şablon değişkeni kesintisi denemeden önce kaldırılır gerçeğini yansıtmak için Columbo ve dyp yorumlarına dayanarak yeniden düzenlendi.

EDİT 2: hvd bilgi, en üst seviye . Göre ^em>cv-elemeleriayrıca kaldırılır. Bu durumda, const char[N] char[N], çünkü olması demektircv-elemeleridizi elemanları uygulamak için dizinin kendisi de (array of const da const array, tabiri caizse); bu değildi belli C 11 standart, ama oldu açıklık C 14.

Yukarıdaki dayanarak, kısmi işlev şablonları sipariş seçmelisiniz derim#2daha özel olarak, aramanın hiçbir belirsizlik ile çözülmesi gerekir.

Şimdi, sert gerçeğe geri. Hem GCC 4.9.1 ve Çınlama 3.5.0, aşağıdaki seçeneklere sahip

-Wall -Wextra -std=c  11 -pedantic 

benzer hata iletileri ile belirsiz olarak gelen aramayı reddetmek için. Çınlama gelen hata:

prog.cc:16:2: error: call to 'f' is ambiguous
    f(7, "ab");
    ^
prog.cc:4:27: note: candidate function [with T = int] 
template<typename T> void f(T, const char*) //#1 
                         ^
prog.cc:9:30: note: candidate function [with N = 3] 
template<std::size_t N> void f(int, const char(&)[N]) //#2 
                            ^

Visual C 2013 IntelliSense (EDG derleyici, bildiğim kadarıyla tabanlı) de belirsiz olarak çağrı bayrak. Tuhaftır, VC derleyici ileri gider ve herhangi bir hata, tercih kodu derler#2. (Yay! Doğru olmalı o zaman beni kabul eder.)

Uzmanlar açık bir soruneden çağrı belirsiz?Ben eksik (kısmi sipariş alanında, tahmin ediyorum)? neyim

CEVAP
21 Aralık 2014, Pazar


Cevap olarak sorunun benim şimdiki anlayış detayları gönderiyorum. Bu konuda son sözü olacak emin değilim, ama gerekirse daha fazla tartışma için bir temel olarak hizmet verebilir. Dyp, hvd ve Columbo açıklamalar bilgi çeşitli bit altında başvurulan bulmak için gerekli.

Tahmin ettiğim gibi, sorun kısmi kuralları işlev şablonları sipariş ile. [14.8.2.4] ( . bölüm ^em>Kısmi sipariş sırasında Deducing şablon değişkenleri), başvuruları kaldırın ve cv ön elemeleri bu dönüşümlerden sonra, yazın kesintinin [14.8.2.5] açıklandığı gibi yapılır diyorBir tür şablon değişkenleri Deducing). Bu bölüm [14.8.2.1] olacağını işlev çağrıları - başvurduğu farklı (Bir işlev çağrısı şablon değişkenleri Deducing).

Ne zaman şablon parametreleri sonucuna işlev bağımsız değişken türleri, bazı özel durumlarda bu izin verilir; örneğin, bir şablon parametresi T kullanılan bir işlev parametre türü T* olabilir sonucuna işlev bağımsız değişken T[i], çünkü dizi için işaretçi dönüştürme izin verilir bu durumda. Ancakbu kısmi sipariş sırasında kullanılan kesintinin süreç değildirhala işlevleri hakkında konuşuyoruz olsa bile.

Kısmi sırasında sipariş aynı kurallar onlar söylemek deducing şablon bağımsız değişkenleri olarak ne zaman şablon değişkeni kesintisi eşleştirme kuralları hakkında düşünmek kolay yolu sanırımsınıf şablonuuzmanlık.

Çamur kadar berrak? Belki bir kaç örnek yardımcı olacaktır.

Bu kuralları kullandığı için çalışırbir işlev çağrısı şablon değişkenleri deducing:

#include <iostream>
#include <type_traits>

template<typename T> void f(T*)
{
    std::cout << std::is_same<T, int>::value << '\n';
}

int main()
{
    int a[3];
    f(a);
}

ve 1 yazdırır.

Bu kuralları kullandığı için mi, yokbir tür şablon değişkenleri deducing:

#include <iostream>

template<typename T> struct A;

template<typename T> struct A<T*>
{
    static void f() { std::cout << "specialization\n"; }
};

int main()
{
    A<int[3]>::f();
}

ve Çınlama gelen hata

error: implicit instantiation of undefined template 'A<int [3]>'

Uzmanlık olamaz T* ve int[3] bu durumda uymuyor çünkü kullanılan, derleyici İlköğretim şablonu oluşturmak için çalışır.

Kısmi sipariş sırasında kullanılan kesintinin bu ikinci tür.


Bizim fonksiyonu geri dönelim şablon bildirimleri:

template<typename T> void f(T, const char*); //#1
template<std::size_t N> void f(int, const char(&)[N]); //#2

Kısmi sıralama olur: işlemimin açıklama

  • İle tartışma indirimi şablon#1parametre olarak#2argüman olarak: M N, T yerine değeri int ama 56**. türünde bir parametre olarak birebir biz icat ^strong>değiltüründe bir değişken char[M], yani maç#2değilen azından uzman olarak#1türleri ikinci çift için.
  • İle tartışma indirimi şablon#2parametre olarak#1argüman olarak: biz icat bir tür U yerine T, int ve U tutmuyor (farklı), bir parametre türü char[N] eşleşmiyor bir argüman tipi const char* ve değeri olmayan bir tür şablon parametre N olamaz sonucuna bağımsız değişkenler, o kadar#1değilen azından uzman olarak#2türleri ya da bir çift için.

Seçilmiş olmak için bir şablon en azından uzman diğer tüm türleri için gereken bu yana, izlerne şablon dışında daha özelve ara belirsiz.


Açıklama yukarıda biraz Core Language Active Issue 1610 benzer bir sorun (hvd tarafından sağlanan bağlantı) tanımına aykırı.

Orada örneğidir:

template<class C> void foo(const C* val) {}
template<int N> void foo(const char (&t)[N]) {}

Yazar, bu şu anda olmaz o, sezgisel olarak, ikinci bir şablon daha özel olarak seçilmiş olmalı ve şablon dışında daha özel ne () savunuyor.

O zaman neden const char[N] kesinti const C* parametre olarak başarısız olmasına neden olan char[N], getirisi const niteleyici kaldırılması olduğunu açıklar.

Ancak, benim şimdiki anlayışa göre, kesinti bu durumda, const ya const hayır başarısız olur. Bu teyit ederek mevcut uygulamalarında Çınlama ve GCC: eğer biz Kaldır const niteleyici parametreleri her iki işlev şablonları ve ara foo() char[3] tartışma çağrısı ise hala belirsiz. Diziler ve işaretçiler sadece kısmi sırasında geçerli kurallar sıralamaya göre uymuyor.

Bunu söyledikten sonra, Komite üyesi değilim, ben şu anda anlamak fazlası da olabilir.


Güncelleme: son zamanlarda 2003 kadar uzanan bir Çekirdek aktif konu: üzerine düşmüşüm issue 402.

Orada örnek 1610 eşittir. Yorum sorunu açıkça bu iki aşırı vardır sırasız göre kısmi bir sıralama algoritması olarak duruyor, tam da o yüzden olmaması dizi için işaretçi kuralları çürüme sırasında kısmi sipariş.

Son yorum:

Bu dava için ideal olacaktır bazı duyguları vardı emretti, ama değer mi bilmiyoruz üzerinde çalışmak için zaman geçirmek şimdi. Eğer kısmi sipariş değişiklikleri bir noktada biraz daha büyük,bakacak olursak bunu tekrar değerlendireceğiz.

Bu nedenle, yukarıda verdiğim yorumun doğru olduğuna gayet eminim.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Abe Olandres

    Abe Olandres

    16 EYLÜL 2006
  • Rayone GB

    Rayone GB

    14 Temmuz 2007
  • UrAvgConsumer

    UrAvgConsume

    1 Ocak 2012