2015-11-02 11 views
12

Mam następujący kod, który nie kompiluje się w Visual C++ 2015, ale działa pod GCC 4.8.4. Zastanawiam się, co jest słuszne? Kod jest tutaj mowa poniżej:przesłonić specyfikator jako parametr szablonu - czy jest prawidłowy?

template <class T> class ATemplate; 
template <class R, class A1> 
    struct ATemplate<R(A1)>{ }; 

int main() 
{ 
    ATemplate<void(int)> x; 
// ATemplate<void(int)override> y; //---Does not compile!!! 
    return 0; 
} 

Czy to źle używać nadpisanie jak specyfikatorem tutaj poniżej (lub const). Podobny kod istnieje w bibliotece GMock, w której do generowania parametru szablonu (w tym nadpisywania) wykorzystywana jest ekspansja makr, a także faktyczny podpis funkcji.

Visual C++ 2015 produkuje następujący błąd podczas wyjmowania wykomentowane wiersz:

x.cpp(11): error C2062: type 'int' unexpected 
x.cpp(11): error C2976: 'ATemplate': too few template arguments 
x.cpp(4): note: see declaration of 'ATemplate' 
x.cpp(11): error C2079: 'y' uses undefined class 'ATemplate' 

jedną z odpowiedzi poniżej wspomnieć, że nadpisać jest bez znaczenia w kontekście wolnych funkcji (ważny punkt) - robi to to znaczy, że GCC jest tutaj błędne. const specyfikator jest również bez znaczenia w tym przypadku (dla darmowych funkcji), ale mimo to dozwolone (przez VC++) ??? Wspomina również, że wirtualne specyfikatory powinny istnieć tylko w deklaracji - to nie ma znaczenia dla tej sprawy (ponieważ nie istnieje żadna definicja). W przypadku słowa kluczowego wirtualnego można pominąć wyprowadzenie, ponieważ nie ma znaczenia, czy kod się kompiluje, ale w przypadku przypadku przesłaniania nie jest on prawidłowy, ponieważ robi dużą różnicę.

Podczas korzystania ReturnType (ArgType Arg) ... możliwe const lub zastąpić specyfikator jako parametr makra (jak GMock robi), ograniczenie narzucone przez VCC wywołuje ten kod nie skompilować (najwyraźniej w przypadku Clang zbyt) . Który jest poprawny?

Standard nie stwierdza, że ​​specyfikator zastąpienia nie będzie używany w tym kontekście (kontekst parametru szablonu?), Prawda?

+0

Sądząc głosów jestem prawdopodobnie brakuje coś oczywistego, ale gdzie jest funkcja chcesz nadpisać? –

+0

@KarolyHorvath nie ma znaczenia –

+0

@KarolyHorvath, tak, to nie ma znaczenia. Opublikowany kod jest minimalny i powoduje błąd. –

Odpowiedz

8

Jest to błąd g ++.

Standard pozwala virt-specyfikatora-sec dwóch produkcji: w funkcji rozdzielczości (tylko dla virtualużytkownika funkcja definicji) w członków declarator. Twój kontekst nie jest ani.

Krótszy demo zachowanie buggy GCC:

void foo(void) override;   // g++ rejects with message: 
            // virt-specifiers in 'foo' 
            // not allowed outside a class definition 
void (*bar)(void) override;  // g++ erroneously accepts 
typedef void baz(void) override; // g++ erroneously accepts 
5

Według standardu override specifier jest kontekstowa i ma szczególne znaczenie tylko gdy jest stosowany po funkcji członka deklaracji; w przeciwnym razie nie jest zarezerwowanym słowem kluczowym.

Więc chciałbym powiedzieć, kod w twoim drugim przykładzie wydaje się bez znaczenia.

Próbowałem skompilować oba przykłady z gcc-5.1.0 (z flagą -S), a one skutkują dokładnie tym samym montażem.

To nie skompilować pod clang-3.7.0 w wyniku następującego błędu:

test.cpp:11:23: error: expected '(' for function-style cast or type construction 

Pracitcally oznacza to, że nie powinno się używać override w ten sposób.

+1

co to oznacza praktycznie w kontekście powyżej? –

+0

@WernerErasmus oznacza, że ​​nie powinieneś tego używać :) –

+0

źle. Twój przykład nie jest taki sam jak mój. –

2

Od 9.2 członków klasy (projekt N4140)

virt-specifier-seq: 
    virt-specifier 
    virt-specifier-seq virt-specifier 
virt-specifier: 
    override 
    final 

[9.2/8]

A virt-specifier-seq shall contain at most one of each virt-specifier. A virt-specifier-seq shall appear only in the declaration of a virtual member function (10.3).

Więc o ile widzę, override nie mogą być stosowane do wolnych funkcji, więc nie spodziewałbym się, że będzie to dozwolone w podpisie/typie funkcji darmowej (nawet jeśli była to część typu, taka jak const).

+0

zastąpienie w kontekście tutaj powyżej nie pojawia się w definicji funkcji (jak nie określiłem definicji), ale widzę twój punkt - Niemniej jednak, pominięcie wirtualne w otrzymanym przypadku nie ma znaczenia, ale pominięcie to robi, dlatego nie można tego traktować tak samo. –

+0

@WernerErasmus nie do końca to, co miałem na myśli, zredagowałem dla wyjaśnienia (mam nadzieję :)) – melak47

Powiązane problemy