[g++ 4.4] ADL issue

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
C++:
1
2
3
4
5
6
7
8
9
10
11
#include <set>
#include <string>

class C;

void set(C&, const std::string&);

void f(C& c)
{
        set(c, std::string());
}
/usr/include/c++/4.4/bits/stl_set.h: In function ‘void f(C&)’:
/usr/include/c++/4.4/bits/stl_set.h:87: error: ‘template<class _Key, class _Compare, class _Alloc> class std::set’ is not a function,
adl.cpp:6: error: conflict with ‘void set(C&, const std::string&)’
adl.cpp:10: error: in call to ‘set’
VC10 vind de code geen probleem en ik eigenlijk ook niet. Wie heeft er gelijk?

ADL: Wikipedia: Argument-dependent name lookup

[ Voor 9% gewijzigd door Olaf van der Spek op 03-02-2011 17:00 ]


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 16:28
Aangezien het in GCC 4.5.2 niet meer te reproduceren is, denk ik dat jij gelijk hebt, en dat je tegen een bug in GCC 4.4 aanloopt. ;) Upgraden is misschien het makkelijkst?

Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
4.5 is beschikbaar in Debian experimental, even kijken of dat in squeeze te installeren is.

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 16:28
Het probleem is trouwens dat 'ie jouw set() verward met std::set. Dat probleem is te omzeilen door jouw functie simpelweg te hernoemen. (Lelijk natuurlijk, maar als 'ie maar beperkt gebruikt wordt is 't misschien een makkelijke workaround.)

Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Nog maar 318 calls.. Hmm, zal ik hem renamen naar zet? :p

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 16:28
edit:
Hmz, blijkbaar snap ik het probleem toch niet helemaal.

edit2:
Eventueel ::set i.p.v set zou dan nog kunnen. Mooi is ook anders.

[ Voor 165% gewijzigd door Soultaker op 03-02-2011 17:30 ]


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
In eerste instantie dacht ik dat ergens een using namespace std; stond, maar dat was ook niet het geval.

4.5 werkt niet mee, maar dat is een ander issue:
/usr/bin/ld: X.cpp.o: undefined reference to symbol 'pthread_getspecific@@GLIBC_2.2.5'
/usr/bin/ld: note: 'pthread_getspecific@@GLIBC_2.2.5' is defined in DSO /lib64/libpthread.so.0 so try adding it to the linker command line
/lib64/libpthread.so.0: could not read symbols: Invalid operation
Ook weer opgelost: http://wiki.debian.org/To...tdependentsharedlibraries

[ Voor 209% gewijzigd door Olaf van der Spek op 03-02-2011 17:59 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je code is iig goed, set is binnen de scope van de functie geen type en dus parst het als een function-call. ADL is op class ctors niet van toepassing.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Die logica volg ik even niet. ADL gaat over name lookup. Dat gebeurt per definitie om uit te vissen of een naam verwijst naar een type of een functie.

Het negeren van types gebeurt later, in overload resolution.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee, de C++ parser regels maken al assumpties over de aard van een identifier. Een type-name heeft een andere terminal dan een nontype. Typisch wordt type informatie geprocessed door de parser (adhv typedef, class, struct, enum en namespace declarations) teruggekoppeld naar de lexer. Dit is ook de hele reden waarom 'typename' zo belangrijk is in templates op dependent names. Zonder 'typename' gaat de parser er vanuit dat het geen type is en volgt hij dus ook niet die productieregels.

Bovendien heeft ADL juist niets te maken met het onderscheid tussen type en functie. Het gaat louter om de names uit verschillende namespaces welke gebruikt moeten worden in de uiteindelijke overload resolution. En die neemt uiteraard alleen de funtie-declaraties uit die geassocieerde namespaces mee. Daarom is deze code ook correct:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
namespace test
{
    struct foo { };
    void bar(foo) { }
    struct bar { };
}

int main()
{
    test::foo f;
    bar(f);
}


De struct 'test::bar' hide eigenlijk de functie 'test::bar'. Toch zijn er geen conflicten, want ADL pakt alleen de functiedeclaraties uit 'test'. Overigens, als je de definities van beide bars omdraait dan is ook duidelijk te zien dat de parser info heeft over type informatie - je krijgt dan een syntax error op de plek van de functiedefinitie, omdat een type (void) gevolgd door een type (bar) niet geldig is.

Ook wordt ADL niet eens toegepast als er een class method wordt gevonden in de huidige scope, wat destemeer aangeeft dat type vs nontype resolutie dan al heeft plaatsgevonden.

[ Voor 62% gewijzigd door .oisyn op 04-02-2011 13:06 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 16:28
Ik denk dat je uitleg verder wel klopt, maar:
.oisyn schreef op vrijdag 04 februari 2011 @ 12:40:
Overigens, als je de definities van beide bars omdraait dan is ook duidelijk te zien dat de parser info heeft over type informatie - je krijgt dan een syntax error op de plek van de functiedefinitie, omdat een type (void) gevolgd door een type (bar) niet geldig is.
Ik denk dat die definities omdraaien wel gewoon mag (je hebt het over regel 4 en 5 toch?) Normaal gesproken kun je niet twee verschillende soorten definities geven van één symbol maar waarschijnlijk mag dit expliciet wel om declaraties die geldig waren in C te behouden, zoals bijvoorbeeld:
C:
1
2
struct foo;
void foo(struct foo *foo);

(Ik weet niet precies hoe dit in C++ geformuleerd is; in C zitten structs in een aparte namespace, waardoor er dus überhaupt geen conflict ontstaat, tenzij je ook b.v. een typedef toevoegt.)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je hebt gelijk. Ik dacht toch echt dat dat een compile error gaf 8)7
Ik zie trouwens dat VC++ bugt, als ik de twee omdraai dan kan ie de functie bar() niet meer vinden bij de aanroep.

[ Voor 46% gewijzigd door .oisyn op 04-02-2011 14:52 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
.oisyn schreef op vrijdag 04 februari 2011 @ 00:01:
Je code is iig goed, set is binnen de scope van de functie geen type en dus parst het als een function-call. ADL is op class ctors niet van toepassing.
Wat als zowel de class (via using std) als de functie in scope zijn? Dan gaat het binnen VC10 ook fout, alhoewel de class geen geldige overload bevat.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dan is het ambigu.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Olaf van der Spek
  • Registratie: September 2000
  • Niet online
Dat is een beetje vervelend. :(
Pagina: 1