2009-10-29 4 views
3

Cette classe:Comment puis-je avoir un constructeur par défaut optionnel?

template <class T> 
struct A { 
    A() : t(T()) { 
    } 

    A(const T& t_) : t(t_) { 
    } 

    T t; 
}; 

ne compilera pas si T ne pas constructeur par défaut. Celui-ci :

template <class T> 
struct A { 
    A(const T& t_) : t(t_) { 
    } 

    T t; 
}; 

sera pas constructeur par défaut, même si T est constructeur par défaut.

Je veux avoir les deux - S'il n'y a pas de T() je ne veux pas de A().

Je sais que SFINAE doit être utilisé. Et que Boost.traits et Boost.enable_if peuvent aider, mais je n'arrive pas à le faire fonctionner. Quelqu'un peut-il me donner un exemple à ce cas simple?

+0

que voulez-vous un() de faire appel à T si T n'a pas de constructeur par défaut? – Mark

+0

S'il n'y a pas de T() je ne veux pas de A() du tout. –

+4

Je peux me tromper, mais êtes-vous sûr que le premier échoue, * si vous n'essayez pas d'utiliser la version par défaut avec un T qui n'a pas le constructeur par défaut *? GCC et Comeau sont d'accord. Comment instanciez-vous la classe? – UncleBens

Répondre

0

Essayez ceci:

template <class T> 
struct A { 
    A(const T& t_ = T()) : t(t_) { 
    } 

    T t; 
}; 
1

fonctions membres de modèles de classe ne sont instanciés si vous les invoquez. Si vous n'invoquez A::A(), le code appelant T::T() ne doit pas être compilé dans ce code:

template <class T> 
struct A { 
    A() : t(T()) { 
    } 
    // ... 
}; 

éprouvez des difficultés à vous avec cela? Si oui, quel compilateur utilisez-vous?

Cela dit, si le code à l'aide A invoque son constructeur par défaut, la seule issue que je vois est de déplacer la création du T au sein A::A() dans une classe de traits:

template< typename T > 
struct default_a_ traits { 
    static T default_construct() 
    { 
    return T(); 
    } 
}; 

template <class T, class Traits = default_a_traits<T> > 
struct A { 
    A() : t(Traits::default_construct()) { 
    } 
    // ... 
}; 

Pour les classes ne pas avoir un constructeur par défaut, vous pouvez fournir une classe de traits qui fournissent des moyens de créer un T d'une autre façon:

struct my_special_traits_for_b { 
    static T default_construct() 
    { 
    return read_b_from_db(); 
    } 
}; 

typedef A<B, special_traits_for_b> AB; 
Questions connexes