[解決済み] [Solved] protectedまたはprivateコンストラクタのみを持つクラスで ::std::make_shared を呼び出すにはどうすればよいですか?
2022-04-08 23:51:22
質問
私はこのコードが動作しませんが、意図は明確だと思います。
testmakeshared.cpp
#include <memory>
class A {
public:
static ::std::shared_ptr<A> create() {
return ::std::make_shared<A>();
}
protected:
A() {}
A(const A &) = delete;
const A &operator =(const A &) = delete;
};
::std::shared_ptr<A> foo()
{
return A::create();
}
でも、コンパイルするとこんなエラーが出ます。
g++ -std=c++0x -march=native -mtune=native -O3 -Wall testmakeshared.cpp
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:52:0,
from /usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/memory:86,
from testmakeshared.cpp:1:
testmakeshared.cpp: In constructor ‘std::_Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp>::_Sp_counted_ptr_inplace(_Alloc) [with _Tp = A, _Alloc = std::allocator<A>, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]’:
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr_base.h:518:8: instantiated from ‘std::__shared_count<_Lp>::__shared_count(std::_Sp_make_shared_tag, _Tp*, const _Alloc&, _Args&& ...) [with _Tp = A, _Alloc = std::allocator<A>, _Args = {}, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr_base.h:986:35: instantiated from ‘std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = std::allocator<A>, _Args = {}, _Tp = A, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:313:64: instantiated from ‘std::shared_ptr<_Tp>::shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = std::allocator<A>, _Args = {}, _Tp = A]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:531:39: instantiated from ‘std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = A, _Alloc = std::allocator<A>, _Args = {}]’
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr.h:547:42: instantiated from ‘std::shared_ptr<_Tp1> std::make_shared(_Args&& ...) [with _Tp = A, _Args = {}]’
testmakeshared.cpp:6:40: instantiated from here
testmakeshared.cpp:10:8: error: ‘A::A()’ is protected
/usr/lib/gcc/x86_64-redhat-linux/4.6.1/../../../../include/c++/4.6.1/bits/shared_ptr_base.h:400:2: error: within this context
Compilation exited abnormally with code 1 at Tue Nov 15 07:32:58
このメッセージは基本的に、テンプレートのインスタンス化スタックにある、あるランダムなメソッドが
::std::make_shared
はコンストラクタが保護されているためアクセスできません。
しかし、私は本当に両方の
::std::make_shared
で指定されていないこのクラスのオブジェクトは作れないようにします。
::std::shared_ptr
. これを実現する方法はあるのでしょうか?
どのように解決するのですか?
この回答 はおそらく良いものであり、私が受け入れそうなものです。しかし、より醜い方法ですが、すべてをインライン化し、派生クラスを必要としない方法も思いつきました。
#include <memory>
#include <string>
class A {
protected:
struct this_is_private;
public:
explicit A(const this_is_private &) {}
A(const this_is_private &, ::std::string, int) {}
template <typename... T>
static ::std::shared_ptr<A> create(T &&...args) {
return ::std::make_shared<A>(this_is_private{0},
::std::forward<T>(args)...);
}
protected:
struct this_is_private {
explicit this_is_private(int) {}
};
A(const A &) = delete;
const A &operator =(const A &) = delete;
};
::std::shared_ptr<A> foo()
{
return A::create();
}
::std::shared_ptr<A> bar()
{
return A::create("George", 5);
}
::std::shared_ptr<A> errors()
{
::std::shared_ptr<A> retval;
// Each of these assignments to retval properly generates errors.
retval = A::create("George");
retval = new A(A::this_is_private{0});
return ::std::move(retval);
}
2017-01-06を編集しています。 他の人がその線で回答を出していて、このことについて混乱しているようだったので、この考え方が引数を取るコンストラクタに明確かつ単純に拡張可能であることを明確にするために変更しました。
関連
-
[解決済み】C++ 非推奨の文字列定数から「char*」への変換について
-
[解決済み】LLVMで暗黙のうちに削除されたコピーコンストラクタの呼び出し
-
[解決済み] エラーが発生する。ISO C++は型を持たない宣言を禁じています。
-
[解決済み】関数名の前に期待されるイニシャライザー
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み】C++ - ステートメントがオーバーロードされた関数のアドレスを解決できない。
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー
-
[解決済み] 配列のベクトルを扱う正しい方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】クラステンプレートの引数リストがない
-
[解決済み】C++のGetlineの問題(オーバーロードされた関数 "getline "のインスタンスがない
-
[解決済み】致命的なエラー LNK1169: ゲームプログラミングで1つ以上の多重定義されたシンボルが発見された
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】1つ以上の多重定義されたシンボルが見つかる
-
[解決済み] 数値定数の前にunqualified-idを付けて、数値を定義することを期待する。
-
[解決済み】Visual Studioのデバッガーエラー。プログラムを開始できません 指定されたファイルが見つかりません
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む