クラステンプレートObj
と関数テンプレート_make_obj
_があります。 Obj
にはprivate
単一のコンストラクターが定義されており、バインドするテンプレート化された型への参照を受け取ります。
_template <typename T>
class Obj {
private:
T& t;
Obj(T& t)
: t{t}
{ }
};
template <typename T>
Obj<T> make_obj(T& t) {
return {t};
}
_
私が望むのは、friend
を作成できるように_make_obj
_関数をObj
として宣言することです。
私はいくつかの友人宣言を試しました
_friend Obj make_obj(T&);
_
そして
_template <typename T1, typename T2>
friend Obj<T1> make_obj(T2&);
_
後者は、Obj
クラスの_make_obj
_友人のすべてのテンプレートのインスタンス化を行う試みとしてはあまり望ましくありません。ただし、これらの両方のケースで同じエラーが発生します。
_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");
^
_
例としてmake_obj("hello");
を実行しようとしています。
Obj
の値コンストラクターへの_make_obj
_アクセスのみを許可するにはどうすればよいですか?
いくつかの前方宣言が必要です。
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);
}
ところで、私はあなたが本当に欲しいとは思わないT & t;
クラスのメンバー変数。多分 T t;
の方が良い選択です;)
自動戻り型構文を使用すると、関数を前方宣言するだけで、すべてが機能します。ここに例があります
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;
}