Masalah dalam GCC / C ++ 17 dengan kelas templat templat

10

Pertimbangkan 2 kelebihan berikut ini

template<typename T>
bool test() {
    return true;
}

template<template<typename ...> class T>
bool test() {
    return false;
}

Yang pertama berfungsi untuk kelas reguler, sedangkan yang kedua berfungsi untuk templat yang tidak dipakai. Contohnya:

    std::cout<<test<int>()<<std::endl; <-- this yields 1
    std::cout<<test<std::list>()<<std::endl; <--this yields 0

Sekarang pertimbangkan fungsi templat berikut:

template<typename U>
bool templfun(){
    struct A{
        bool f(){
            return test<A>(); // <-- this gives an error
        }
    };
    return test<A>();  // <-- this is ok
}

Dalam GCC itu memberikan kesalahan untuk resolusi kelebihan ambigu, sementara Dentang mengkompilasi. Menariknya, panggilan kedua untuk menguji () tidak menghasilkan kesalahan (bahkan dalam GCC). Apalagi, jika saya menghapus template<typename U>benda di atas templfun, gcc berhenti mengeluh.

Apakah ini bug dengan GCC atau itu kode ilegal?

Marieddu
sumber

Jawaban:

4

GCC salah; struct Aadalah entitas templated tetapi jelas bukan templat (karena tidak dimulai dengan templatekata kunci), jadi tidak ada ambiguitas.

Untuk mengonfirmasi, kita dapat mengganti nama parameter tipe untuk melihat bahwa G ++ sedang mencoba untuk menggunakan templat-templat berlebih.

template <typename X>
bool test() {
    return true;
}

template <template <typename...> class Y>
bool test() {
    return false;
}

template <typename U>
bool templfun() {
    struct A {
        bool f() {
            return test<A>(); // <-- this gives an error
        }
    };
    return test<A>(); // <-- this is ok
}

bool run() {
    return templfun<int>();
}

Output G ++: ( tautan ke godbolt )

<source>:15:27: error: call of overloaded 'test<templfun() [with U = int]::A>()' is ambiguous
   15 |             return test<A>(); // <-- this gives an error
      |                    ~~~~~~~^~

<source>:2:6: note: candidate: 'bool test() [with X = templfun() [with U = int]::A]'
    2 | bool test() {
      |      ^~~~

<source>:7:6: note: candidate: 'bool test() [with Y = templfun()::A]'
    7 | bool test() {
      |      ^~~~

Jelas " candidate: 'bool test() [with Y = templfun()::A]'" itu palsu.

Perhatikan bahwa tipe lokal tidak diizinkan sebagai argumen templat sebelum C ++ 11 (lihat C ++ 03 § 14.3.1.2), sehingga dapat menjelaskan kompleksitas implementasi G ++.

rustyx
sumber