2016-11-11 2 views
13

je tente de définir une classe A comme suit:Type de variable membre doit dépendre le type d'argument constructeur

template< typename T > 
class A 
{ 
    public: 
    A(T elem) 
     : _elem(elem) 
    {} 

    private: 
    TYPE _elem; // "TYPE" should be either "T" in case "elem" is an r-value or "T&" in case "elem" is an l-value. 
}; 

Ici, je veux _elem avoir soit le type T dans le cas où l'argument du constructeur elem est un r-value ou le type T& dans le cas elem est une valeur de l.

Est-ce que quelqu'un sait comment cela peut être implémenté?

+1

Je ne suis pas assez intelligent pour écrire ceci pour vous, mais vous y parvenez en utilisant template * specialization *. Upvoted pour attirer l'attention. – Bathsheba

+0

J'ai aussi eu besoin de cela (en écrivant des classes de vue) ... –

Répondre

12

Jusqu'à ce que nous obtenons template argument deduction for class templates, vous aurez besoin d'utiliser une fonction d'aide pour cela:

template <typename T> 
auto make_a (T&& elem) { 
    return A<T>{std::forward<T>(elem)}; 
} 

Il utilise une référence de transfert pour en déduire si l'argument est une lvalue ou rvalue et construit le A par parfaitement le transfert l'argument. Prenant int à titre d'exemple, si un lvalue est passé, T sera int&, et si un rvalue est passé, T sera .

Votre modèle A devrait simplement ressembler à ceci:

template< typename T > 
class A 
{ 
    public: 
    A(T elem) 
     : _elem(elem) 
    {} 

    private: 
    T _elem; 
}; 

Vous pourriez faire make_a un ami et faire le constructeur privé si vous ne souhaitez que pour permettre la construction de la méthode de fabrication.

+0

Pourquoi std :: move utilise-t-il un constructeur de A? – themagicalyang

+0

@themagicalyang Oups, habitude. – TartanLlama

+0

Quand une valeur r est passée, pourquoi T alors 'int' et pas' int && '? –