質問内容
私はSFINAEとconceptを使い、
スマートポインタのテンプレート引数Typeに依存せずに
入力された下記オブジェクトを判別できるはずの関数
identificationを作成しました。
- std::unique_ptr<Type>
- std::shared_ptr<Type>
- std::weak_ptr<Type>
- ポインタ(動的配列)
- 静的配列
- その他すべて
しかしテンプレート引数Typeをint[]とするとエラーが発生してしまいます。
エラー文を読んでも何が言いたいのかよくわからないです。
どのように書けばエラーを抑えることができるでしょうか。
あとconceptは勉強し始めたばかりで慣れていませんので
あまり良い書き方でない部分があれば
教えていただければ幸いです。
ご回答どうかよろしくお願い致します。
どんどん追記していくうちに文字数制限に引っかかってしまったのでので元コードを
wandboxへ移動しました。
エラー文
terminal
1[ 50%] Building CXX object CMakeFiles/a.out.dir/main.cpp.o 2[ソースのパス]/main.cpp:112:20: error: call to deleted constructor of 'std::unique_ptr<int [], std::default_delete<int []> >' 3 identification(heap_array); 4 ^~~~~~~~~~ 5 6/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/unique_ptr.h:689:7: note: 'unique_ptr' has been explicitly marked deleted here 7 unique_ptr(const unique_ptr&) = delete; 8 ^ 9 10[ソースのパス]/main.cpp:76:28: note: passing argument to parameter here 11auto identification(auto...)noexcept{ // その他が入力された場合実行 12 ^
####エラー内容
- error:'std::unique_ptr<int[]、std::default_delete<int[]>>'の削除されたコンストラクターの呼び出し
何が言いたいのか私にはわかりません。
- note:「unique_ptr」はここで明示的に削除済みとしてマークされています
これも何が言いたいのか私にはわかりません。
- note: ここに引数をパラメータに渡します
この部分はコード中のエラーの発生する部分をコメントアウト
すれば消えるので恐らく今回の問題とは直接関係ないかもしれないです。
開発環境の備考
上記コードはすべてc++20でコンパイルするものとする。
ツールの種類 | ツールの名前 | バージョン |
---|---|---|
コンパイラ | clang++ | 10.0.0 |
OS | Linux Mint | 20.0 |
追記
Bearded-Ockhamさんの回答を元に修正した
問題を解決するためのコードを下記に記す。
c++
1#include <iostream> 2#include <memory> 3#include <vector> 4 5/////////////////// 6// 7// コンセプト定義 8// 9/////////////////// 10template<typename Type> concept IsUniquePtr = requires(Type type1, Type& type2){ // std::unique_ptrか判別 11 type1 = nullptr; 12 type1.release(); 13 type1.reset(); 14 type1.swap(type2); 15 type1.get(); 16 type1.get_deleter(); 17 //*type1; <- ここがエラーの原因 18 type1.operator bool(); 19}; 20 21template<typename Type> concept IsSharedPtr = requires(Type type1, Type& type2){ // std::shared_ptrか判別 22 type1 = type2; 23 type1.reset(); 24 type1.swap(type2); 25 type1.get(); 26 //*type1; <- はstd::shared_ptr<int[]>が入力されたときetcと表示してしまう原因となる。 27 type1.use_count(); 28 type1.unique(); 29 type1.operator bool(); 30 type1.owner_before(type2); 31}; 32 33template<typename Type> concept IsWeakPtr = requires(Type type1, Type& type2){ // std::weak_ptrか判別 34 type1 = type2; 35 type1.swap(type2); 36 type1.reset(); 37 type1.use_count(); 38 type1.expired(); 39 type1.lock(); 40 type1.owner_before(type2); 41}; 42 43template<typename Type> concept IsPointer = std::is_pointer_v<Type>; // ポインタ化判別 44template<typename Type> concept IsArray = std::is_array_v<Type>; // 配列か判別 45 46//////////////////////////////////// 47// 48// スマートポインタや配列の識別関数 49// 50//////////////////////////////////// 51template<IsUniquePtr Up> 52auto identification(const Up&)noexcept{ // unique_ptrが入力された場合実行 53 std::cout << "unique_ptr" << std::endl; 54} 55 56template<IsSharedPtr Sp> 57auto identification(const Sp&)noexcept{ // shared_ptrが入力された場合実行 58 std::cout << "shared_ptr" << std::endl; 59} 60 61template<IsWeakPtr Wp> 62auto identification(const Wp&)noexcept{ // weak_ptrが入力された場合実行 63 std::cout << "weak_ptr" << std::endl; 64} 65 66template<IsPointer Pt> 67auto identification(const Pt&)noexcept{ // ポインタが入力された場合実行 68 std::cout << "pointer" << std::endl; 69} 70 71template<IsArray Ar> 72auto identification(const Ar&)noexcept{ // 配列が入力された場合実行 73 std::cout << "array" << std::endl; 74} 75 76auto identification(auto...)noexcept{ // その他が入力された場合実行 77 std::cout << "etc" << std::endl; 78} 79 80////////////// 81// 82// メイン関数 83// 84////////////// 85int main(){ 86 // スマートポインタの型には依存しない 87 using UseType = float; 88 //using Type = int; 89 //using Type = std::vector<int>; 90 91 // スマートポインタや配列や動的配列確保 92 auto unique_ptr_mem = std::make_unique<UseType>(); 93 auto shared_ptr_mem = std::make_shared<UseType>(); 94 auto weak_ptr_mem = std::weak_ptr<UseType>(); 95 auto vector_mem = std::vector<UseType>(); 96 auto pointer_mem = new UseType[3]; 97 UseType array_mem[3]; 98 99 identification(unique_ptr_mem);// unique_ptrと表示される(正常) 100 identification(shared_ptr_mem);// shared_ptrと表示される(正常) 101 identification(weak_ptr_mem);// weak_ptrと表示される(正常) 102 identification(pointer_mem);// pointerと表示される(正常) 103 identification(array_mem);// arrayと表示される(正常) 104 identification(vector_mem);// etcと表示される(正常) 105 106 delete[] pointer_mem; 107 108 // 109 // ここから問題の部分 110 // 111 auto heap_array = std::make_unique<int[]>(5); 112 identification(heap_array);// unique_ptrと表示される!!!(正常) 113 114 return 0; 115} 116
追記
yohhoyさんの回答を元に修正した
問題を解決するためのコードを下記に記す。
c++
1#include <iostream> 2#include <memory> 3#include <vector> 4 5//////////////////////////////////////////////////////////////////////////////////////////// 6// 7// コンセプト定義 8// 9// 備考: 10// typename スマートポインタ::element_typeでスマートポインタのテンプレート引数を参照可能 11// 12// また、スマートポインタの場合テンプレート引数が配列か否かで作られるクラス形が異なるので 13// コンセプトはそれらのコンセプトの論理和でなければならない。 14// 15//////////////////////////////////////////////////////////////////////////////////////////// 16 17template<typename Type> concept IsUniquePtr = // std::unique_ptrか判別 18 std::is_same_v<Type, std::unique_ptr<typename Type::element_type>> // テンプレート引数が配列型以外の場合 19 || std::is_same_v<Type, std::unique_ptr<typename Type::element_type[]>>; // テンプレート引数が配列型の場合 20 21template<typename Type> concept IsSharedPtr = // std::shared_ptrか判別 22 std::is_same_v<Type, std::shared_ptr<typename Type::element_type>> // テンプレート引数が配列型以外の場合 23 || std::is_same_v<Type, std::shared_ptr<typename Type::element_type[]>>; // テンプレート引数が配列型の場合 24 25template<typename Type> concept IsWeakPtr = // std::weak_ptrか判別 26 std::is_same_v<Type, std::weak_ptr<typename Type::element_type>> // テンプレート引数が配列型以外の場合 27 || std::is_same_v<Type, std::weak_ptr<typename Type::element_type[]>>; // テンプレート引数が配列型の場合 28 29 30template<typename Type> concept IsPointer = std::is_pointer_v<Type>; // ポインタか判別 31template<typename Type> concept IsArray = std::is_array_v<Type>; // 配列か判別 32 33//////////////////////////////////// 34// 35// スマートポインタや配列の識別関数 36// 37//////////////////////////////////// 38inline auto identification(IsUniquePtr auto const &){ // unique_ptrが入力された場合実行 39 std::cout << "unique_ptr" << std::endl; 40} 41 42inline auto identification(IsSharedPtr auto const &){ // shared_ptrが入力された場合実行 43 std::cout << "shared_ptr" << std::endl; 44} 45 46inline auto identification(IsWeakPtr auto const &){ // weak_ptrが入力された場合実行 47 std::cout << "weak_ptr" << std::endl; 48} 49 50inline auto identification(IsPointer auto const &){ // ポインタが入力された場合実行 51 std::cout << "pointer" << std::endl; 52} 53 54inline auto identification(IsArray auto const &){ // 配列が入力された場合実行 55 std::cout << "array" << std::endl; 56} 57 58inline auto identification(auto...){ // その他が入力された場合実行 59 std::cout << "etc" << std::endl; 60} 61 62////////////// 63// 64// メイン関数 65// 66////////////// 67int main(){ 68 // スマートポインタの型には依存しない 69 using UseType = float; 70 //using Type = int; 71 //using Type = std::vector<int>; 72 73 //配列などの定数 74 constexpr size_t size = 5; 75 76 // スマートポインタや配列や動的配列確保 77 auto unique_ptr_mem = std::make_unique<UseType>(); 78 auto shared_ptr_mem = std::make_shared<UseType>(); 79 auto weak_ptr_mem = std::weak_ptr<UseType>(); 80 auto vector_mem = std::vector<UseType>(); 81 auto pointer_mem = new UseType[size]; 82 UseType array_mem[size]; 83 84 identification(unique_ptr_mem); // unique_ptrと表示される(正常) 85 identification(shared_ptr_mem); // shared_ptrと表示される(正常) 86 identification(weak_ptr_mem); // weak_ptrと表示される(正常) 87 identification(pointer_mem); // pointerと表示される(正常) 88 identification(array_mem); // arrayと表示される(正常) 89 identification(vector_mem); // etcと表示される(正常) 90 91 delete[] pointer_mem; 92 93 // 94 // ここから問題の部分 95 // 96 std::cout << std::endl << "-----ここからスマートポインタを使った動的配列の部分-----" << std::endl; 97 98 auto heap_array_unique = std::make_unique<int[]>(size); 99 auto heap_array_shared = std::make_shared<int[]>(size); 100 auto heap_array_weak = std::weak_ptr<int[]>(heap_array_shared); 101 102 identification(heap_array_unique); // unique_ptrと表示される!!!!!(正常) 103 identification(heap_array_shared); // shared_ptrと表示される!!!!!(正常) 104 identification(heap_array_weak); // weak_ptrと表示される!!!!!(正常) 105 106 return 0; 107} 108
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2020/08/04 23:19 編集