[C++] lookup en templates

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Ik kwam de volgende situatie tegen:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
namespace N {

template <typename T>
class A {
public:
   friend void foo(const A<T>& a) {}
   friend void bar(const A<T>& a) {}
};

template <typename T>
class B {
public:
   void bar() {}
   
   void test() {
      N::A<T> a;
      foo(a);    // CALL 1
      bar(a);   // CALL 2
   }
};

}

void bar() {}

int main() {
   N::B<int> b;

   b.test();

   return 0;
}

Het probleem zit hem in CALL 2. CALL 1 gaat goed, omdat er (volgens mij) via ADL/Koenig wordt gezocht in de namespace van het argument 'a', en de functie daar wordt gevonden. Echter, bij CALL 2 wordt de juiste functie verborgen door de eigen class member bar() en krijg je een fout over 'too many arguments'. PRefixen met bv N::bar(a) werkt ook niet; dan kan hij de functie niet vinden in N.

Hoe kan ik zorgen dat de compiler toch de juiste functie vindt? (errors overigens getest met Comeau)

---

Oh, dit fixed het... nvm

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
namespace N {

template <typename T>
class A {
public:
   friend void foo(const A<T>& a) {}

template <typename U>
friend void bar(const A<U>& a);

private:
mutable int x;
};

template <typename T>
void bar(const A<T>& a) {a.x = 5;}


template <typename T>
class B {
public:
   void bar() {}
   
   void test() {
      N::A<T> a;
      foo(a);
      N::bar(a);
   }
};

}

void bar() {}

int main() {
   N::B<int> b;

   b.test();

   return 0;
}

[ Voor 23% gewijzigd door Zoijar op 18-08-2012 12:16 ]


Acties:
  • 0 Henk 'm!

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

.oisyn

Moderator Devschuur®

Demotivational Speaker

Als je gebruik wilt blijven maken van ADL dan kun je ook de call naar bar wrappen in een functie (die niet bar heet) buiten de class, zodat je geen last meer hebt van de name hiding binnen de class.

Ik heb even geen standaard bij de hand om het te verifiëren, maar volgens mij maakt een friend declaration een name niet expliciet vindbaar in de enclosing namespace. Meestal wordt aangeraden om functies in zo'n geval ook altijd expliciet te definiëren.

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!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
.oisyn schreef op zaterdag 18 augustus 2012 @ 22:42:
Als je gebruik wilt blijven maken van ADL dan kun je ook de call naar bar wrappen in een functie (die niet bar heet) buiten de class, zodat je geen last meer hebt van de name hiding binnen de class.
Ohja, dat zou ook nog kunnen. Maar plaatst wel een burden op de gebruiker van een library, dus liever niet.
Ik heb even geen standaard bij de hand om het te verifiëren, maar volgens mij maakt een friend declaration een name niet expliciet vindbaar in de enclosing namespace. Meestal wordt aangeraden om functies in zo'n geval ook altijd expliciet te definiëren.
Volgens mij is dat het ook. Er was altijd al iets ingewikkelds met friend templates dat hij die niet kon vinden, maar ik kan het me niet precies meer herinneren. Expliciet definieren werkt in ieder geval voor zover ik nu zie goed. Uiteraard moet je dan wel N::bar(a) schrijven, maar dat lijkt me duidelijk voor een gebruiker als je zelf die naam verbergt met een van je eigen functies.