MSVC: union vs. klasse / struct med inline venn operatører

stemmer
0

Denne delen av koden kompilerer og kjører som forventet på GCC 3.x og 4.x:

#include <stdio.h>

typedef union buggedUnion
{   
public:
            // 4 var init constructor
        inline buggedUnion(int _i) {
            i = _i;
        }

        friend inline const buggedUnion operator - (int A, const buggedUnion &B) {
            return buggedUnion(A - B.i);
        }

        friend inline const buggedUnion operator - (const buggedUnion &A, const buggedUnion &B) {
            return buggedUnion(A.i - B.i);
        }

        int i;

} buggedUnion;

int main()
{
    buggedUnion first(10);
    buggedUnion second(5);

    buggedUnion result = 10 - (first - second);

    printf(%d\n, result.i); // 0

    return 0;
}

MSVC, men vil ikke kompilere den koden, klager:

main.cpp(60) : error C3767: '-': candidate function(s) not accessible
        could be the friend function at 'main.cpp(41)' : '-'  [may be found via argument-dependent lookup]
        or the friend function at       'main.cpp(45)' : '-'  [may be found via argument-dependent lookup]
main.cpp(60) : error C2676: binary '-' : 'buggedUnion' does not define this operator or a conversion to a type acceptable to the predefined operator

Hvilke av kompilatorer er riktig? Hvordan kan dette løses? Jeg prøver å oppnå ren kode (ingen utenfor venne metoder) og samtidig opprettholde mobilitet, fleksibilitet og selv dokumentere kode.

Noen notater:

  • Dette er en test-case for å vise problemet, er den opprinnelige datatypen mye mer sofistikert og nøye designet, om enn ikke fungerer i MSVC (hoved kompilatoren er GCC, men MSVC kompatibilitet er også ønskelig).
  • Legge 'public:' i starten av unionen erklæringen ikke løse det.
  • Legge til 'offentlig:' før hver operatør ikke løser det
  • Konvertering testen saken til en struct / klasse gjør fikse det, men dette er ikke ønskelig (Vennligst ingen flammer, jeg fikk grunner. De fleste av dem er begrensninger i C ++ språk)
  • Operatør metode er å stå på globale området (ikke et medlem funksjon)

Optimale løsning ville ikke stole på å bevege erklæring utsiden av unionen definisjonen for estetiske grunner (over 24 forskjellige kombinasjoner av operatører og operander), men vil bli gjort dersom det ikke er noen annen løsning.

Publisert på 12/07/2009 klokken 07:07
kilden bruker
På andre språk...                            


3 svar

stemmer
1

Det er vanskelig å si hvilken som er riktig, siden ikke navngitte structs er ikke tillatt med standard (selv om de er en vanlig forlengelse), og som sådan programmet er dårlig utformet.

Edit : Det ser ut til å være en feil i MSVC, siden følgende kode, noe som er helt gyldig, ikke klarer å kompilere.

union buggedUnion
{
    friend buggedUnion operator - (int A, const buggedUnion &B) {
        return B;
    }

    friend buggedUnion operator - (const buggedUnion &A, const buggedUnion &B) {
        return A;
    }

    int i;
};


int main()
{
    buggedUnion first = { 1 };
    buggedUnion second = { 1 };
    buggedUnion result = 3 - (first - second);
}

Du kan omgå dette ved å definere funksjonene utenfor klassen.

union buggedUnion
{
    int i;
};

buggedUnion operator - (int A, const buggedUnion &B) {
    return B;
}

buggedUnion operator - (const buggedUnion &A, const buggedUnion &B) {
    return A;
}

Du kan til og med beholde venn status ved å erklære funksjonene inne i klassen (men fortsatt definere dem utenfor), men jeg tviler på at du noen gang vil trenge det i en fagforening.

Legg merke til at jeg fjernet den unødvendige typedefog inlines.

Svarte 12/07/2009 kl. 07:28
kilden bruker

stemmer
0

Følgende kode kompilerer riktig i Visual C ++ 2008:

union buggedUnion
{
    int i;

    friend buggedUnion operator - (int A, const buggedUnion &B);
    friend buggedUnion operator - (const buggedUnion &A, const buggedUnion &B);
};

buggedUnion operator - (int A, const buggedUnion &B)
{
    return B;
}

buggedUnion operator - (const buggedUnion &A, const buggedUnion &B)
{
    return A;
}

Mens dokumentasjon MSDN sier at å skrive definisjonen av venn funksjon inne i en klasse faktisk setter funksjonen i filen omfang, synes dette å ikke fungere for fagforeninger. Siden det fungerer for klassen og struct, jeg mistenker at dette kan være en bug. Siden innføringen jeg har gitt ovenfor skal fungere på GCC, tror jeg det kan betraktes som en egnet løsning, og feilen vil sannsynligvis ikke bli løst i MSVC.

Svarte 12/07/2009 kl. 08:00
kilden bruker

stemmer
0

Du trenger å erklære dem som venn funksjon i omsluttende omfang, som når du erklære dem i klassen, de er ikke lenger synlig i den ytre rammen. Så enten flytte funksjonen kroppen ut av klassen som avakar sagt, eller holde dem i klassen og legge til følgende linje å gjeninnføre navnet til den omsluttende omfang:

extern const buggedUnion operator-(const buggedUnion& A, const buggedUnion&B);

int main()
{
    ...etc

Håper dette hjelper. Ikke sikker på om det er en bug, men det ser ut (?) For meg å være korrekt oppførsel, nå implementert på riktig måte, som mange kompilatorer brukes til å tolke annerledes. Se: --ffriend-injeksjon i http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Dialect-Options.html .

Svarte 12/07/2009 kl. 07:59
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more