Belirsiz Aşırı Yük Şablonları


16

Aşağıdaki şablon kodu var

#include <vector>
#include <array>
#include <iostream>

template<typename T1>
void foo(std::vector<T1> bar) {
    std::cout << "GENERIC" << std::endl;
}

template<typename T1>
void foo(std::vector<std::vector<T1>> bar) {
    std::cout << "SPECIFIC (vector)" << std::endl;
}

template<typename T1, int SIZE>
void foo(std::vector<std::array<T1, SIZE>> bar) {
    std::cout << "SPECIFIC (array)" << std::endl;
}

int main() {
    std::vector<std::vector<int>> a(2, std::vector<int> { 1, 2, 3});
    std::vector<std::array<int, 3>> b(2, std::array<int, 3> {4, 5, 6});

    foo(a);
    foo(b);
}

hangi üretir

SPECIFIC (vector)
GENERIC

Neden vektör-vektör sürüm belirli bir şablon ile çağrıldığını merak ediyorum, ama dizi-vektör sürüm genel ile çağrılır?


2
Bilginize: Aynı sorunu, vectorhepsini dıştan kaldırarak basitleştirebilirsiniz . Buraya bakın
ChrisMM

@ChrisMM iyi yakalama. Bu örnek, iç içe geçmiş yapının gerekli olduğu üretim kodumdan sentezlendi.
Xaser

5
MSVC, dizilerin vektörü sürümünü çağırır: godbolt.org/z/7Gfeb0
R2RT

Yanıtlar:


8
template<typename T1, size_t SIZE>
void foo(std::vector<std::array<T1, SIZE>> bar) {
    std::cout << "SPECIFIC (array)" << std::endl;
}

Bunun std::size_tyerine kullanmalısınız int. buraya koş

Edit: Aslında, senin yorum ve kod hakkındaki sezgi beni konuya kazmak için yol açtı. İlk bakışta, (benim gibi) standart geliştirici dönüştürmek için derleyici beklemek intiçin std::size_t(her ikisi de ayrılmaz türüdür ve dolaylı dönüştürme çok önemsiz olduğu için) ve açılan menüden void foo(std::vector<std::array<T1, SIZE>> bar)iyi uzmanlaşma olarak. Yani şablon argüman kesinti sayfasını okurken bunu buldum:

Parametre listesinde tür olmayan bir şablon parametresi kullanılırsa ve karşılık gelen şablon bağımsız değişkeni çıkarılırsa, çıkarılan şablon bağımsız değişkeninin türü (ekteki şablon parametre listesinde belirtildiği gibi, anlam referansları korunur) türüyle eşleşmelidir cv niteleyicilerinin bırakılması ve şablon bağımsız değişkeninin bağlı bir diziden çıkarılması haricinde tam olarak tür olmayan şablon parametresi - bu durumda herhangi bir integral türüne izin verilir, hatta her zaman doğru olacak olsa bile bool:

Her zaman olduğu gibi, elbette, bunun ne anlama geldiğini anlamak için bir kereden fazla okumak zorundasınız :)

Böylece ilginç bir sonuç ortaya çıkıyor.

Zaten istediğimiz uzmanlık seçilmedi, ancak derleyici seçmek zorunda kalsaydı, bir hata olurdu.

template<typename T1, int SIZE>
void foo(std::vector<std::array<T1, SIZE>> bar) {
    std::cout << "SPECIFIC (array)" << std::endl;
}

int main() {
    std::vector<std::array<int, 3>> b(2, std::array<int, 3> {4, 5, 6});

    foo(b); // P = std::vector<std::array<int,(int)SIZE>
            // A = std::vector<std::array<int,(unsigned_long)SIZE>>
            // error: deduced non-type template argument does not have the same
            // type as its corresponding template argument */
}

kodu çalıştır

Bir başka ilginç şey:

Tür olmayan şablon bağımsız değişkeni çıkarılmasaydı, bağımsız değişken ve şablon türlerini aynı olmaya zorlayan bir kısıtlama olmazdı.

#include <vector>
#include <array>
#include <iostream>

template<typename T1, int SIZE>
void foo(std::vector<std::array<T1, SIZE>> bar) {
    std::cout << "SPECIFIC (array)" << std::endl;
}

int main() {
    std::vector<std::array<int, 3>> b(2, std::array<int, 3> {4, 5, 6});

    foo<int,3>(b);
}

kodu çalıştır


@Xaser çünkü dizinin ikinci şablon argümanı tiptedir size_t...
Jean-Baptiste Yunès

2
R2RT'nin yorumu dikkate alındığında, derleyiciye özgü farklılıklar olduğu görülmektedir.
Xaser

8

Ben düşünüyorum bundan sadece nedeniyle bir satır olduğunu[temp.deduct.call]/4

Genel olarak, tümdengelim işlemi, sonuçlanan A'yı A ile özdeş kılacak şablon bağımsız değişken değerlerini bulmaya çalışır.

İyi netleştirmek için, Agelen vasıtaları parametre[temp.deduct.call]/1

... çağrının karşılık gelen argümanının türüyle şablon argüman kesinti (A olarak adlandırın) ...

Daha önce değişen, işaret edilmiştir template<typename T1, int SIZE>için template<typename T1, size_t SIZE>düzeltmeleri yapmanın karşılaştığınız sorunu. Belirtildiği gibi [temp.deduct.call]/4, derleyici Aaynı olanı çıkarmaya çalışıyor A. Bir std::arrayşablon bağımsız değişkenleri <class T, size_t N>(from [array.syn]) olduğundan, ikinci parametre aslında size_tdeğildir int.

Bu nedenle, şablon kesinti için, genel işleviniz tam olarak türüyle template<typename T1>eşleşebilir ; burada uzmanınız tam bir eşleşme değildir . MSVC'nin çıkarılmasında yanlış olduğuna inanıyorum.Atemplate<typename T1, int SIZE>

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.