c++ - friendship - declarar la función de amigo de plantilla de la clase de plantilla
friendship and inheritance c++ (2)
Tengo una plantilla de clase Obj
y una plantilla de función make_obj
. Obj
tiene un constructor único private
definido, que toma una referencia a su tipo de plantilla para vincularse.
template <typename T>
class Obj {
private:
T& t;
Obj(T& t)
: t{t}
{ }
};
template <typename T>
Obj<T> make_obj(T& t) {
return {t};
}
Lo que quiero es declarar la función make_obj
un friend
para que pueda crear Obj
''s, pero nadie más puede hacerlo (excepto a través de la copia ctor).
He intentado varias declaraciones de amigos incluyendo
friend Obj make_obj(T&);
y
template <typename T1, typename T2>
friend Obj<T1> make_obj(T2&);
Este último es un intento poco deseable de hacer todas las make_obj
de plantilla de make_obj
amigos de la clase Obj
. Sin embargo, en ambos casos me sale el mismo error:
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");
^
tratando de hacer make_obj("hello");
para fines de ejemplo.
¿Cómo puedo permitir que solo make_obj
acceda al contructor de valor de Obj
?
Con la sintaxis de tipo de retorno automático, solo necesita reenviar declarar la función y todo funciona. Aquí hay un ejemplo
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;
}
Necesitas unas pocas declaraciones hacia adelante:
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);
}
Y BTW: No creo que realmente quieras T & t;
para la variable miembro de su clase. Probablemente T t;
Es una mejor opción;)