C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

type traits

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French)
View previous topic :: View next topic  
Author Message
Arnaud Debaene
Guest





PostPosted: Wed Jul 28, 2004 6:54 pm    Post subject: type traits Reply with quote



Je suis en train d'implémenter une librairie assez simpliste de type de
traits. La structure de base ressemble à çà :
template <class TType> struct type_traits
{
typedef TType type;
typedef TType* pointer;
typedef TType& ref;
static TType instance(); //not implemented
static const bool isPointer=false;
//autres champs
};

//diverses spécialisations de type_traits pour TType*, TType&, etc...

Maintenant, j'essaie d'implémenter des fonctionnalité pour comparer les
types entre eux (fortement inspiré de Loki). Par exemple :
template <class Base, class Derived> struct IsBaseAndDerived
{
private:
struct big {char mem[2];};

struct IsBaseAndDerivedHelper
{
static big TestFct(typename type_traits<Base>::pointer);
static char TestFct(...);
};

public:
static const bool value =
(sizeof(reinterpret_cast<typename type_traits(0))
//1
== sizeof(char));
};

template <class Base> struct IsBaseAndDerived <Base, Base>
{
static const bool value = true;
};

template <class Derived> struct IsBaseAndDerived <void, Derived>
{
static const bool value=false;
};

J'ai des problèmes d'utilisation dans certains cas :

struct VirtualClass
{
virtual void f() =0;
};

struct S {};

bool is_derived=IsBaseAndDerived<C, VirtualClass>::value; //*

g++ 3.1 accepte de compiler la ligne //*, mais VC7.1 et Comeau online
refusent car, lors de l'instantiation, ils se plaignent que VirtualClass est
virtuelle et qu'ils ne peuvent donc pas implémenter type_traits::instance().

Qui a raison? Et si le code est effectivement faux, comment le corriger
(dans la mesure du possible, j'aimerais conserver instance() dans
type_traits).

Arnaud


Back to top
Fabien LE LEZ
Guest





PostPosted: Thu Jul 29, 2004 9:03 am    Post subject: Re: type traits Reply with quote



On Wed, 28 Jul 2004 20:54:26 +0200, "Arnaud Debaene"
<adebaene (AT) club-internet (DOT) fr>:

Quote:
template <class Base, class Derived> struct IsBaseAndDerived
...
(sizeof(reinterpret_cast<typename type_traits(0))

Euh... pour les histoires de dérivation, c'est pas plutôt
dynamic_cast<> qu'il faut tester ?


--
;-)

Back to top
drkm
Guest





PostPosted: Thu Jul 29, 2004 12:29 pm    Post subject: Re: type traits Reply with quote



Fabien LE LEZ <gramster (AT) gramster (DOT) com> writes:

Quote:
On Wed, 28 Jul 2004 20:54:26 +0200, "Arnaud Debaene"
[email]adebaene (AT) club-internet (DOT) fr[/email]>:

template <class Base, class Derived> struct IsBaseAndDerived
...
(sizeof(reinterpret_cast<typename type_traits(0))

Euh... pour les histoires de dérivation, c'est pas plutôt
dynamic_cast<> qu'il faut tester ?

Je dirais tout simplement un static_cast<>. Il ne peut utiliser de
dynamic_cast, puisque l'on se trouve à la compilation. Il surcharge
donc une fonction, l'une prenant un pointeur sur Base, et l'autre un
nombre d'argument variable. Les deux renvoient des types de donnée de
tailles différentes. Tout cela est bien connu à la compilation. On
teste alors la taille du retour d'un appel de la fonction avec un
simple pointeur null. Le cast sert à donner le type du pointeur null.

Si je me souviens bien, les arguments variables sont nécessaire pour
accepter n'importe quel type d'argument, sans fournir de meilleur
match pour Derived, comme le ferait un modèle de fonction membre.

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html

Back to top
Arnaud Debaene
Guest





PostPosted: Thu Jul 29, 2004 4:00 pm    Post subject: Re: type traits Reply with quote

Fabien LE LEZ <gramster (AT) gramster (DOT) com> wrote

Quote:
On Wed, 28 Jul 2004 20:54:26 +0200, "Arnaud Debaene"
[email]adebaene (AT) club-internet (DOT) fr[/email]>:

template <class Base, class Derived> struct IsBaseAndDerived
...
(sizeof(reinterpret_cast<typename type_traits(0))

Euh... pour les histoires de dérivation, c'est pas plutôt
dynamic_cast<> qu'il faut tester ?

Non, le but là c'est de créer un pointeur vers le type dérivé
(Derived* dans le cas général, autre chose si Derived correspond à des
spécialisations de type_traits).

De toute façon, le tout est dans un sizeof, donc ce code n'est jamais
executé, il ne génère même pas de code compilé! C'est juste un test à
la compilation!

Arnaud

Back to top
Falk Tannhäuser
Guest





PostPosted: Fri Jul 30, 2004 9:08 am    Post subject: Re: type traits Reply with quote

Fabien LE LEZ wrote:
Quote:

On Wed, 28 Jul 2004 20:54:26 +0200, "Arnaud Debaene"
[email]adebaene (AT) club-internet (DOT) fr[/email]>:

template <class Base, class Derived> struct IsBaseAndDerived
...
(sizeof(reinterpret_cast<typename type_traits(0))

Pourquoi pas "sizeof(typename type_traits<Derived>::pointer)" tout simplement ?

Falk

Back to top
drkm
Guest





PostPosted: Fri Jul 30, 2004 11:31 am    Post subject: Re: type traits Reply with quote

Falk Tannhäuser <falk.tannhauser (AT) crf (DOT) canon.fr> writes:

Quote:
Fabien LE LEZ wrote:

On Wed, 28 Jul 2004 20:54:26 +0200, "Arnaud Debaene"
[email]adebaene (AT) club-internet (DOT) fr[/email]>:

template <class Base, class Derived> struct IsBaseAndDerived
...
(sizeof(reinterpret_cast<typename type_traits(0))

Pourquoi pas "sizeof(typename type_traits<Derived>::pointer)" tout
simplement ?

Parce qu'il s'agit en fait, je pense, de :

typedef typename type_traits< Derived >::pointer Pointer ;
... = sizeof( TestFct( static_cast< Pointer >( 0 ) ) ) ;

J'ai changé le reinterpret_cast<> en static_cast<> ; je pense que ça
ne change rien au comportement, mais c'est la manière idiomatique
d'obtenir un pointeur null typé selon nos besoins. Mais surtout, je
pense qu'il manquait l'appel à TestFct(). Correct ?

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html

Back to top
Arnaud Debaene
Guest





PostPosted: Fri Jul 30, 2004 2:34 pm    Post subject: Re: type traits Reply with quote

Falk Tannhäuser <falk.tannhauser (AT) crf (DOT) canon.fr> wrote

Quote:
Fabien LE LEZ wrote:

On Wed, 28 Jul 2004 20:54:26 +0200, "Arnaud Debaene"
[email]adebaene (AT) club-internet (DOT) fr[/email]>:

template <class Base, class Derived> struct IsBaseAndDerived
...
(sizeof(reinterpret_cast<typename type_traits(0))

Pourquoi pas "sizeof(typename type_traits<Derived>::pointer)" tout simplement ?


Parce que j'ai écrit n'importe quoi dans mon premier post Wink Je
reprnds donc :

template <class TType> struct type_traits
{
typedef TType type;
typedef TType* pointer;
typedef TType& ref;
static TType instance(); //not implemented
static const bool isPointer=false;
//autres champs
};

//diverses spécialisations de type_traits pour TType*, TType&, etc...

template <class Base, class Derived> struct IsBaseAndDerived
{
private:
struct big {char mem[2];};

struct IsBaseAndDerivedHelper
{
static big TestFct(typename type_traits<Base>::pointer);
static char TestFct(...);
};

public:
static const bool value =
(sizeof(IsBaseAndDerivedHelper::TestFct(reinterpret_cast<typename
type_traits(0))) == sizeof(big));
};

template <class Base> struct IsBaseAndDerived <Base, Base>
{
static const bool value = true;
};

template <class Derived> struct IsBaseAndDerived <void, Derived>
{
static const bool value=false;
};



Et le cas d'utilisation qui pose problème est :

struct VirtualClass
{
virtual void f() =0;
};

struct S {};

bool is_derived=IsBaseAndDerived<S, VirtualClass>::value;


Effectivement, on pourrait remplacer le reinterpret_cast par un
static_cast, mais je tenais à mettre en exergue que ce n'est pas une
manipulation normale de pointeur, mais juste un "truc" pour comparer 2
types.

Pour revenir à ma question intiale : Il semblerait que GCC a tort
d'accepter ce code car lorsque l'on écrit
type_traits<Derived>::pointer, il faut garantir que toute la
déclaration de type_traits<Derived> est valide. Dans mon cas, c'est
impossible car il est illégal pour une méthode de retourner par valeur
une classe abstraite.

Arnaud

Back to top
drkm
Guest





PostPosted: Fri Jul 30, 2004 3:34 pm    Post subject: Re: type traits Reply with quote

[email]adebaene (AT) club-internet (DOT) fr[/email] (Arnaud Debaene) writes:

Quote:
Effectivement, on pourrait remplacer le reinterpret_cast par un
static_cast, mais je tenais à mettre en exergue que ce n'est pas une
manipulation normale de pointeur, mais juste un "truc" pour comparer 2
types.

Je pense au contraire que le « truc » consiste à comparer les
tailles d'un type sentinelle et du type de retour d'une fonction. Le
cast n'est là que pour donner un type précis au pointeur null.
L'utilisation idiomatique est alors static_cast<>, il me semble.

Lorsque j'ai vu reinterpret_cast<>, je me suis arrêté, et me suis
demandé pourquoi tu avais utilisé un tel cast, comme d'habitude
lorsque je rencontre un reinterpret_cast<>. Je pense que cela fait se
poser des questions inutiles au lecteur de ton code. Avec un
static_cast<>, il se concentre plutôt sur le « truc » de la
comparaison des tailles.

AMHA.

--drkm, en recherche d'un stage : http://www.fgeorges.org/ipl/stage.html

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (French) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.