質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

608閲覧

decltype()を用いた変数宣言ができない

yosswi414

総合スコア7

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/03/20 03:15

C++の機能(テンプレートなど)の学習・練習目的で以下のようにマージソートを書いたら, 大量のエラー(およそ10000文字)を吐かれました。
しかし、エラーを読んでも自分の書いたソースの部分が無く、原因がわかりません。

出来る範囲でいろいろ試してみたところ、

l.24 std::vector<decltype(*first)> v((size_t)dist);

の部分に問題があることがわかり、
このdecltype(*first)を例えばintlong等にすると動きました(ソートもきちんとされていました)。しかし、例えば

C++

1if(typeid(decltype(*first)) == typeid(int)) cout<<"It's same!"<<endl;

のようなコードを書いて検証すると、条件式は真と評価されるので、やはり*firstの型は(以下のコードの場合)int型で合っているように思えます。
一体何が原因なのか思い当たりません。どなたかご教示ください。

該当のソースコード

C++

1#include <iostream> 2#include <vector> 3#include <algorithm> 4#include <random> 5 6using Distance = long long; 7 8template<class ContainerItr> 9void MergeSort(const ContainerItr first, const ContainerItr last){ 10 if(first+1==last)return; 11 12 const ContainerItr mid = first + std::distance(first,last)/2; 13 ContainerItr itrFormer = first, itrLatter = mid; 14 15 const Distance dist = std::distance(first,last); 16 Distance distFormer = std::distance(first,mid); 17 Distance distLatter = std::distance(mid,last); 18 19 MergeSort(first,mid); 20 MergeSort(mid,last); 21 22 // 問題の起きた箇所 23 std::vector<decltype(*first)> v((size_t)dist); 24 25 // 例えばContainerItrがstd::vector<int>::iteratorのとき,この問題の箇所を次の行のようにすれば動く 26 // std::vector<int> v((size_t)dist); 27 28 for(int i=0;i<dist;++i) { 29 if (distFormer && distLatter) 30 v[i] = *(*itrFormer <= *itrLatter ? (distFormer--, itrFormer++) : (distLatter--, itrLatter++)); 31 else v[i] = *(distFormer ? (distFormer--, itrFormer++) : (distLatter--, itrLatter++)); 32 } 33 // マージした結果を元のコンテナに戻す 34 for(auto itr=first;itr!=last;++itr)*itr = v[std::distance(first,itr)]; 35} 36 37// vectorの要素を1行に並べて標準出力 38template<class PrintableIterator> 39void PrintVec(PrintableIterator first, PrintableIterator last){ 40 std::cout<<*first; 41 for(auto itr=first+1;itr!=last;++itr)std::cout<<" "<<*itr; 42 std::cout<<std::endl; 43} 44 45using namespace std; 46 47#define NUM (1<<6) 48int main(){ 49 random_device seed_gen; 50 mt19937_64 engine(seed_gen()); 51 uniform_int_distribution<> distr(1,NUM); 52 vector<int> vm(NUM); 53 54 // vm[i]を1~NUMの範囲の乱数で初期化 55 for(int i=0;i<NUM;++i)vm[i]=distr(engine); 56 cout<<"\nvm initialized\n"; 57 58 if(NUM<100)PrintVec(vm.begin(),vm.end()); 59 MergeSort(vm.begin(),vm.end()); 60 if(NUM<100)PrintVec(vm.begin(),vm.end()); 61 62 // ソートされたかどうかチェック 63 cout<<(is_sorted(vm.begin(),vm.end())?"":"not ")<<"sorted: "<<NUM<<endl; 64 65 return 0; 66}

エラーメッセージ

※あまりに長く文字数制限を優に超えてしまうので、主観でどうでも良さそうなところを削りました
※セキュリティ上の理由により、エラーメッセージ中のパスの一部を省略しています
(...が省略部分です)

In file included from C:/.../c++/ext/alloc_traits.h:36:0, from ... from C:\Users...\main.cpp:1: C:/.../c++/bits/alloc_traits.h: In instantiation of 'struct std::allocator_traits<std::allocator<int&> >': ... C:\Users...\main.cpp:24:35: required from 'void MergeSort(ContainerItr, ContainerItr) [with ContainerItr = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]' C:\Users...\main.cpp:62:34: required from here C:/.../c++/bits/alloc_traits.h:392:27: error: forming pointer to reference type 'int&' using pointer = _Tp*; ^ C:/.../c++/bits/alloc_traits.h:395:39: error: forming pointer to reference type 'int&' using const_pointer = const _Tp*; ^ In file included from C:/.../c++/bits/basic_string.h:40:0, from ... from C:\Users...\main.cpp:1: C:/.../c++/ext/alloc_traits.h: In instantiation of 'struct __gnu_cxx::__alloc_traits<std::allocator<int&> >': ... C:\Users...\main.cpp:24:35: required from 'void MergeSort(ContainerItr, ContainerItr) [with ContainerItr = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]' C:\Users...\main.cpp:62:34: required from here C:/.../c++/ext/alloc_traits.h:66:23: error: no members matching '__gnu_cxx::__alloc_traits<std::allocator<int&> >::_Base_type {aka std::allocator_traits<std::allocator<int&> >}::allocate' in '__gnu_cxx::__alloc_traits<std::allocator<int&> >::_Base_type {aka struct std::allocator_traits<std::allocator<int&> >}' using _Base_type::allocate; ^~~~~~~~ C:/.../c++/ext/alloc_traits.h:67:23: error: no members matching '__gnu_cxx::__alloc_traits<std::allocator<int&> >::_Base_type {aka std::allocator_traits<std::allocator<int&> >}::deallocate' in '__gnu_cxx::__alloc_traits<std::allocator<int&> >::_Base_type {aka struct std::allocator_traits<std::allocator<int&> >}' using _Base_type::deallocate; ^~~~~~~~~~ In file included from C:/.../c++/x86_64-w64-mingw32/bits/c++allocator.h:33:0, from ... from C:\Users...\main.cpp:1: C:/.../c++/ext/new_allocator.h: In instantiation of 'class __gnu_cxx::new_allocator<int&>': ... C:\Users...\main.cpp:24:35: required from 'void MergeSort(ContainerItr, ContainerItr) [with ContainerItr = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]' C:\Users...\main.cpp:62:34: required from here C:/.../c++/ext/new_allocator.h:63:26: error: forming pointer to reference type 'int&' typedef _Tp* pointer; ^~~~~~~ C:/.../c++/ext/new_allocator.h:64:26: error: forming pointer to reference type 'int&' typedef const _Tp* const_pointer; ^~~~~~~~~~~~~ In file included from C:/.../c++/string:41:0, from ... from C:\Users...\main.cpp:1: C:/.../c++/bits/allocator.h: In instantiation of 'class std::allocator<int&>': ... C:\Users...\main.cpp:24:35: required from 'void MergeSort(ContainerItr, ContainerItr) [with ContainerItr = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]' C:\Users...\main.cpp:62:34: required from here C:/.../c++/bits/allocator.h:113:26: error: forming pointer to reference type 'int&' typedef _Tp* pointer; ^~~~~~~ C:/.../c++/bits/allocator.h:114:26: error: forming pointer to reference type 'int&' typedef const _Tp* const_pointer; ^~~~~~~~~~~~~ In file included from C:/.../c++/vector:64:0, from C:\Users...\main.cpp:2: C:/.../c++/bits/stl_vector.h: In instantiation of 'class std::vector<int&, std::allocator<int&> >': C:\Users...\main.cpp:24:35: required from 'void MergeSort(ContainerItr, ContainerItr) [with ContainerItr = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]' C:\Users...\main.cpp:62:34: required from here C:/.../c++/bits/stl_vector.h:247:20: error: no members matching 'std::vector<int&, std::allocator<int&> >::_Base {aka std::_Vector_base<int&, std::allocator<int&> >}::_M_allocate' in 'std::vector<int&, std::allocator<int&> >::_Base {aka struct std::_Vector_base<int&, std::allocator<int&> >}' using _Base::_M_allocate; ^~~~~~~~~~~ C:/.../c++/bits/stl_vector.h:248:20: error: no members matching 'std::vector<int&, std::allocator<int&> >::_Base {aka std::_Vector_base<int&, std::allocator<int&> >}::_M_deallocate' in 'std::vector<int&, std::allocator<int&> >::_Base {aka struct std::_Vector_base<int&, std::allocator<int&> >}' using _Base::_M_deallocate; ^~~~~~~~~~~~~ C:/.../c++/bits/stl_vector.h:920:7: error: forming pointer to reference type 'int&' data() _GLIBCXX_NOEXCEPT ^~~~ C:/.../c++/bits/stl_vector.h:924:7: error: forming pointer to reference type 'int&' data() const _GLIBCXX_NOEXCEPT ^~~~ C:/.../c++/bits/stl_vector.h:953:7: error: 'void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = int&; _Alloc = std::allocator<int&>; std::vector<_Tp, _Alloc>::value_type = int&]' cannot be overloaded push_back(value_type&& __x) ^~~~~~~~~ C:/.../c++/bits/stl_vector.h:939:7: error: with 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = int&; _Alloc = std::allocator<int&>; std::vector<_Tp, _Alloc>::value_type = int&]' push_back(const value_type& __x) ^~~~~~~~~ In file included from C:/.../c++/bits/range_access.h:36:0, from ... from C:\Users...\main.cpp:1: C:/.../c++/initializer_list: In instantiation of 'class std::initializer_list<int&>': C:\Users...\main.cpp:24:35: required from 'void MergeSort(ContainerItr, ContainerItr) [with ContainerItr = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]' C:\Users...\main.cpp:62:34: required from here C:/.../c++/initializer_list:54:26: error: forming pointer to reference type 'int&' typedef const _E* iterator; ^~~~~~~~ C:/.../c++/initializer_list:55:26: error: forming pointer to reference type 'int&' typedef const _E* const_iterator; ^~~~~~~~~~~~~~ mingw32-make.exe[3]: *** [CMakeFiles\untitled1.dir\build.make:62: CMakeFiles/untitled1.dir/main.cpp.obj] Error 1 mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:67: CMakeFiles/untitled1.dir/all] Error 2 mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:79: CMakeFiles/untitled1.dir/rule] Error 2 mingw32-make.exe: *** [Makefile:117: untitled1] Error 2

補足

コンパイラはgcc(MinGW)、IDEはCLionを使用しています。
コンパイラは次のマクロで調べたところ、C++17までサポートしていました。

C++

1// バージョンチェック 2#ifdef __cpp_rvalue_references 3 cout<<"C++11 supported"<<endl; 4#endif 5#ifdef __cpp_binary_literals 6 cout<<"C++14 supported"<<endl; 7#endif 8#ifdef __cpp_hex_float 9 cout<<"C++17 supported"<<endl; 10#endif

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

decltypeでトラブるくらいなら素直に iterator_traits 使った方が幸せかも。

C++

1#include <iterator> 2... 3std::vector<std::iterator_traits<ContainerItr>::value_type> v((size_t)dist);

投稿2019/03/20 10:07

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yosswi414

2019/03/20 16:16 編集

回答ありがとうございます。 そのコードを試してみましたが、また別のエラーが出てしまいました。 (エラーメッセージによるとtype/value mismatchとのことです) ただ、参考になればよいのですが、 std::vector<typename std::iterator_traits<ContainerItr>::value_type> v((size_t)dist) とするとコンパイルが通りました(動作も確認しました)。 iterator_traitsについてはよく知らなかったので調べてみます。ありがとうございました。
episteme

2019/03/20 23:16

そか。ご指摘のとおり、value_typeが型であることを明示するため typenameが必要です。
guest

0

ベストアンサー

こんにちは。

*ポインタ型とした場合、参照になります。std::vectorは参照を指定できませんのでエラーになっているようです。std::std::remove_reference_t(要c++14)でいけると思います。

C++

1#include <type_traits> 2 3// : 4 5std::vector<std::remove_reference_t<decltype(*first)>> v((size_t)dist); 6

(コンパイルしていないのでエラーがでたらすいません。)

投稿2019/03/20 05:40

編集2019/03/20 05:41
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yosswi414

2019/03/20 16:18

回答ありがとうございます。 コンパイルできたので、ベストアンサーにさせていただきます。 remove_reference_tは知らなかったので、調べてみます。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問