[C++] Waarom geen explicit specialization in class?

Pagina: 1
Acties:

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Waarom mag dit eigenlijk niet?

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template <typename T>
class Foo {
public:
   template <int N> void bar() {}
   template <> void bar<0>() {} // not allowed

   template <int N, int M> void f() {}
   template <int M> void f<0, M>() {} // impossible for members!

   template <int N> struct X {};
   template <> struct X<0>{}; // not allowed

   template <int N, int M> struct X{};
   template <int M> struct X<0, M>{}; // this IS allowed!

   template <int N> void outofclass() {}
};

template <typename T> template <> void Foo<T>::outofclass<0>() {} 
// outer template not fully specialized: not allowed. This would be fine if Foo was not a class template.

Erg vreemd allemaal. Wordt hier naar gekeken voor de nieuwe C++ standaard? Mijn oplossing is nu zo lang maar dit:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
template <typename T>
class Foo {
private:
   template <int N, int Dummy> struct Internal {
      static void f() {}
   };
   template <int Dummy> struct Internal<0, Dummy> {
      static void f() {}
   };
public:
   void x() { Internal<5, 0>::f();}
};

Maar ik vind het eigenlijk best wel lelijk. Is er nog een andere oplossing? Waarom mag ik wel een partial specialization doen, maar geen volledige? Rationale?

[ Voor 9% gewijzigd door Zoijar op 08-09-2005 10:48 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:02

.oisyn

Moderator Devschuur®

Demotivational Speaker

Opmerkelijk is ook dat, hoewel het voor classes idd wel kan, het niet out of class werkt (je hebt hier een functie outofclass waar het sowieso niet voor mag, ook niet in-class, maar als je het een class zou zijn dan zou het ook niet mogen buiten de class maar wel erbinnen 8)7)

Overigens laat MSVC++ 7.1 het in-class specializen van function templates wel toe, maar dat helpt je zeker niet? ;)

[ Voor 19% gewijzigd door .oisyn op 08-09-2005 11:20 ]

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.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
.oisyn schreef op donderdag 08 september 2005 @ 11:18:
Opmerkelijk is ook dat, hoewel het voor classes idd wel kan, het niet out of class werkt (je hebt hier een functie outofclass waar het sowieso niet voor mag, ook niet in-class, maar als je het een class zou zijn dan zou het ook niet mogen buiten de class maar wel erbinnen 8)7)
Ja, precies, vreemd...
Overigens laat MSVC++ 7.1 het in-class specializen van function templates wel toe, maar dat helpt je zeker niet? ;)
Hehe, nee dat was juist het punt. Mijn code compiled ineens niet meer onder gcc 3.3.3 ... maar dat is inmiddels dus wel opgelost. Ik moest het even kwijt hoe raar dit in elkaar zit.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Ergens denk ik dat dit stiekem een vraag voor mij is :) TopicReminder set.

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


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
MSalters schreef op donderdag 08 september 2005 @ 14:13:
Ergens denk ik dat dit stiekem een vraag voor mij is :) TopicReminder set.
O-)

offtopic:
Pftfft ontmoedigende dag... ik heb het idee dat ik niets weet van C++... of van wat dan ook eigenlijk...

Nog zoiets:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename X, typename Y>
class Foo {
public:
    void bar() {}
};

// ok
template <>
void Foo<int, int>::bar() {}

// not allowed
template <typename Y>
void Foo<int, Y>::bar() {}

Ik ben alle regels kwijt op het moment lol, kan het niet ordenen... Hoe specialize ik een enkele member functie op partieel class niveau?

[ Voor 38% gewijzigd door Zoijar op 08-09-2005 18:52 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Eerste vraag: waarom? De code is vaak duidelijker als je het niet doet.

Forward bijvoorbeeld elke bar( ) naar Foo_impl_bar<X>::bar<Y>( ) en specialiseer de hele Foo_impl_bar, of forward naar een overload set.

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


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
MSalters schreef op vrijdag 09 september 2005 @ 18:17:
Eerste vraag: waarom? De code is vaak duidelijker als je het niet doet.

Forward bijvoorbeeld elke bar( ) naar Foo_impl_bar<X>::bar<Y>( ) en specialiseer de hele Foo_impl_bar, of forward naar een overload set.
Zoiets doe ik nu ook, maar je kan dus niet de hele Foo_impl_bar specializeren, want dan is het een explicit specialization on non-namespace scope. Nu kan je een functie ook niet partieel specializeren, dus een dummy toevoegen kan niet. Het ging om non-type template parameters, dus ik kan ook niet overloaden... De oplossing is dus om er een struct van te maken die ik partieel kan specializeren, en daar een static functie van aanroepen (net als Foo::Internal boven) Alleen heb je dan geen this pointer, dus die moet je ook nog meegeven... Een behoorlijk gedoe voor een simpel concept.

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
template <int X, typename T>
class Foo {
public:
    // f() needs to adapted in the special case of X == 0
    void f() {
    //  a /= X;
    //  this->template f_<X>();
        F_<X, 0>::f(this);
    }

    // not allowed, explicit spec. non-namespace scope
//  template <int N> void f_() {}
//  template <> void f_<0>() {}

    template <int N, int D>
    struct F_ {
        static void f(const Foo<X, T>& self) { self.a /= X;}
    };
    template <int D>
    struct F_<0, D> {
        static void f(const Foo<X, T>& self) {self.a = 0;}
    };

private:
    int a_;
};

// not allowed
//template <typename T>
//void Foo<0, T>::f() {}


Dat moet toch makkelijker kunnen? (zonder dan terug te vallen op TMP technieken met een if-then-else select op basis van X) Ik zou die struct F_ nog uit de class kunnen halen, maar dan moet ik het weer een (template) friend maken, bovendien is het dan niet geencapsuleerd...

Het gaat overigens om het idee. Want volgens mij kan je net zo goed gewoon "X == 0 ? a = 0 : a /= X; doen, en compileert dat ook naar een constante expressie.
offtopic:
oh specialiseren is met een s in het nederlands... dus al die z's in nederlandse woorden vervangen ;)

[ Voor 8% gewijzigd door Zoijar op 09-09-2005 21:32 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Ben ik nou gek of zoek je gewoon een free functie
C++:
1
2
inline template< int D > int div ( int a ) { return a/D; }
inline template< > int div<0> ( int a ) { return 0; }

D'r is helemaal geen dependency van f op T

Ik begin een antwoord te vermoeden. Er zijn grofweg twee mogelijkheden als je twee parameters hebt. Of ze zijn orthogonaal, en dan kun je een functie splitsen, of ze zijn niet orthogonaal en dan heb je geen behoefte aan een partiele specialisatie op 1 parameter.

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


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Topicstarter
Hmmm ik weet niet of dat kon, ik heb de code even niet bij de hand hier... het is wel iets om naar te kijken ja, ik heb wel het gevoel dat het simpeler kan.

Ik bedacht ook net nog dit, herinnerde me ineens modern C++ design :)

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
template <int N> struct Int2Type {enum {v = N};};

template <int X, typename T>
class Foo {
public:
    // f() needs to adapted in the special case of X == 0
    void f() {
        this->f_(Int2Type<X>());
    }

    template <int N> void f_(const Int2Type<N>& dummy) {}
    void f_(const Int2Type<0>& dummy) {}
...

[ Voor 7% gewijzigd door Zoijar op 10-09-2005 12:28 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:02

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zoijar schreef op donderdag 08 september 2005 @ 18:43:
Nog zoiets:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
template <typename X, typename Y>
class Foo {
public:
    void bar() {}
};

// ok
template <>
void Foo<int, int>::bar() {}

// not allowed
template <typename Y>
void Foo<int, Y>::bar() {}
Hier kan ik wel een antwoord bij bedenken: je moet altijd de complete template lijst van een bestaande specialization precies overnemen, omdat de compiler anders nooit weet voor welke van de specializations jij die method nou wil definieren:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<class T, int I> struct Foo
{
    void bar();
};

template<class T> struct Foo<T, 0>
{
    void bar();
};

template<class T> struct Foo<T, 1>
{
};

template<class T> void Foo<T, 1>::bar() { } // #1
template<int I> void Foo<int, I>::bar() { } // #2

Waar hoort #1 nou bij? Foo<T,1> heeft geen bar(), maar als wat jij aangeeft zou mogen dan zou hij net zo goed bij de unspecialized Foo kunnen horen. En waar moet hij #2 nou aan binden? Wederom, voor een Foo<int,1> zou hij niet bestaan, maar voor een Foo<int,0> wel.

offtopic:
woohoo eerste post vanaf mijn nieuwe internet in mijn nieuwe huis \o/

[ Voor 4% gewijzigd door .oisyn op 12-09-2005 22:38 ]

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.

Pagina: 1