web-dev-qa-db-fra.com

déclarer la fonction ami modèle de la classe modèle

J'ai un modèle de classe Obj et un modèle de fonction make_obj. Obj a un private constructeur unique défini, qui prend une référence à son type de modèle pour se lier à.

template <typename T>
class Obj {
  private:
    T& t;
    Obj(T& t)
        : t{t}
    { }
};

template <typename T>
Obj<T> make_obj(T& t) { 
    return {t};
}

Ce que je veux, c'est déclarer la fonction make_objfriend pour qu'elle puisse créer des Obj, mais personne d'autre ne peut (sauf via le ctor copie).


J'ai essayé plusieurs déclarations d'amis, y compris

friend Obj make_obj(T&);

et

template <typename T1, typename T2>
friend Obj<T1> make_obj(T2&);

Ce dernier étant une tentative peu souhaitable de faire toutes les instanciations de modèle de make_obj Amis de la classe Obj. Cependant, dans les deux cas, j'obtiens la même erreur:

error: calling a private constructor of class 'Obj<char const[6]>'
    return {t};
           ^

note: in instantiation of function template specialization
      'make_obj<const char *>' requested here
    auto s = make_obj("hello");
             ^

essayer de faire make_obj("hello"); à des fins d'exemple.

Comment puis-je autoriser uniquement make_obj À accéder au facteur de valeur de Obj?

34
Ryan Haining

Vous avez besoin de quelques déclarations à terme:

template <typename T>
class Obj;

template <typename T>
Obj<T> make_obj(T t);

template <typename T>
class Obj {
private:
    T & t;
    Obj (T & t) : t(t) { }
    Obj() = delete;

    friend Obj make_obj<T>(T t);
};

template <typename T>
Obj<T> make_obj(T t) { 
    return Obj<T>(t);
}

exemple en direct

Et BTW: Je ne pense pas que vous vouliez vraiment T & t; pour la variable membre de votre classe. Probablement T t; est un meilleur choix;)

46
Daniel Frey

Avec la syntaxe de type de retour automatique, il vous suffit de déclarer la fonction en avant et tout fonctionne. Voici un exemple

template <typename T>
auto make_obj(T t);

template <typename T>
class Obj {
private:
    T & t;
    Obj (T & t) : t(t) { }
    Obj() = delete;

    friend auto make_obj<T>(T t);
};

template <typename T>
auto make_obj(T t) {
    return Obj<T>{t};
}

int main() {
    make_obj(1);
    return 0;
}

https://ideone.com/3k86gx

3
Curious