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

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

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

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

Q&A

解決済

2回答

12983閲覧

[c++] 入れ子になったテンプレートクラスのメンバ関数の特殊化。。。

yama_da

総合スコア73

C++

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

0グッド

0クリップ

投稿2017/05/06 04:17

編集2017/05/06 04:21

こんにちは。タイトル通りですが、入れ子になったテンプレートクラスのメンバ関数の特殊化の方法が分かりません。。。

c++

1#include <iostream> 2 3// コンテナクラス 4template <class T> class container 5{ 6public: 7 // イテレータの種類をクラス名で表す 8 struct normal_iterator_type; 9 struct hoge_iterator_type; 10 struct hogehoge_iterator_type; 11 12 // イテレータのテンプレート 13 template <typename iterator_type> struct template_iterator 14 { 15 // 共通の処理 16 void shared_func() 17 { 18 std::cout << "template_iterator::shared_func()" << '\n'; 19 } 20 21 // 個別の処理 22 void individual_func() 23 { 24 std::cout << "template_iterator::individual_func()" << '\n'; 25 } 26 }; 27 28 using iterator = template_iterator<normal_iterator_type>; 29 using hoge_iterator = template_iterator<hoge_iterator_type>; 30 using hogehoge_iterator = template_iterator<hogehoge_iterator_type>; 31 32 // イテレータ取得関数 33 iterator begin(); 34 hoge_iterator begin_hoge(); 35 hogehoge_iterator begin_hogehoge(); 36}; 37 38/** 39 * イテレータ取得関数の定義 40 */ 41template <class T> 42typename container<T>::iterator container<T>::begin() 43{ 44 return container<T>::iterator(); 45} 46 47template <class T> 48typename container<T>::hoge_iterator container<T>::begin_hoge() 49{ 50 return container<T>::hoge_iterator(); 51} 52 53template <class T> 54typename container<T>::hogehoge_iterator container<T>::begin_hogehoge() 55{ 56 return container<T>::hogehoge_iterator(); 57} 58 59// /** 60// * 個別処理関数の特殊化 61// */ 62template <class T> 63template <> 64void container<T>::iterator::individual_func() 65{ 66 std::cout << "iterator::individual_func()" << '\n'; 67} 68 69template <class T> 70template <> 71void container<T>::hoge_iterator::individual_func() 72{ 73 std::cout << "hoge_iterator::individual_func()" << '\n'; 74} 75 76template <class T> 77template <> 78void container<T>::hogehoge_iterator::individual_func() 79{ 80 std::cout << "hogehoge_iterator::individual_func()" << '\n'; 81} 82 83int main(int argc, char const *argv[]) { 84 85 container<int> ctn; 86 auto itr = ctn.begin(); 87 auto itr_hoge = ctn.begin_hoge(); 88 auto itr_hogehoge = ctn.begin_hogehoge(); 89 90 itr.shared_func(); 91 itr_hoge.shared_func(); 92 itr_hogehoge.shared_func(); 93 itr.individual_func(); 94 itr_hoge.individual_func(); 95 itr_hogehoge.individual_func(); 96 97 return 0; 98} 99

上記はいま作っているコンテナクラスの簡単なモデルです。イテレータを数種類持たせたいのですが、すべてに対してクラスを作るとコードが多くなってしまうので、イテレータのテンプレートを1つ作って、共通の機能(++,--,==等)はテンプレートクラス内に書き、個別の機能は、イテレータの種類によって挙動の変わる関数を特殊化して、コード量を減らそうと思ったのですが、その特殊化の部分が上手く行きません。(以下コンパイル結果)

xxx@xxx-HP-Notebook:~/dev/cpp$ gcc -Wall test3.cpp -lstdc++ -std=c++11 -o test3 test3.cpp:67:11: error: invalid explicit specialization before ‘>’ token  template <>            ^ test3.cpp:67:11: error: enclosing class templates are not explicitly specialized test3.cpp:68:46: error: invalid use of incomplete type ‘struct container<T>::template_iterator<container<T>::normal_iterator_type>’  void container<T>::iterator::individual_func()                                               ^ test3.cpp:13:40: note: declaration of ‘struct container<T>::template_iterator<container<T>::normal_iterator_type>’   template <class iterator_type> struct template_iterator                                         ^ test3.cpp:74:11: error: invalid explicit specialization before ‘>’ token  template <>            ^ test3.cpp:74:11: error: enclosing class templates are not explicitly specialized test3.cpp:75:51: error: invalid use of incomplete type ‘struct container<T>::template_iterator<container<T>::hoge_iterator_type>’  void container<T>::hoge_iterator::individual_func()                                                    ^ test3.cpp:13:40: note: declaration of ‘struct container<T>::template_iterator<container<T>::hoge_iterator_type>’   template <class iterator_type> struct template_iterator                                         ^ test3.cpp:81:11: error: invalid explicit specialization before ‘>’ token  template <>            ^ test3.cpp:81:11: error: enclosing class templates are not explicitly specialized test3.cpp:82:55: error: invalid use of incomplete type ‘struct container<T>::template_iterator<container<T>::hogehoge_iterator_type>’  void container<T>::hogehoge_iterator::individual_func()                                                        ^ test3.cpp:13:40: note: declaration of ‘struct container<T>::template_iterator<container<T>::hogehoge_iterator_type>’   template <class iterator_type> struct template_iterator

初めは基点になるイテレータクラスを作って、そこから派生させたのですが、オーバーロードしなければならないかつ中身が親クラスのそれとほとんど同じような関数(=,+=,+等)がたくさんあり、派生させた意味があまりないような気がしたので、こちらの方法に変更したところです。

理想の実行結果はこんなかんじです。

template_iterator::shared_func() template_iterator::shared_func() template_iterator::shared_func() iterator::individual_func() hoge_iterator::individual_func() hogehoge_iterator::individual_func()

回答よろしくお願いします。

環境

gcc version 5.4.1 20160904 (Ubuntu 5.4.1-2ubuntu1~16.04)

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

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

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

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

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

guest

回答2

0

自己解決

こちらのサイトを参考にしました。

c++

1#include <iostream> 2 3// コンテナクラス 4template <class T> class container 5{ 6public: 7 // イテレータのテンプレート 8 template <typename iterator_type> struct template_iterator; 9 // イテレータの種類をクラス名で表す 10 struct normal_iterator_type; 11 struct hoge_iterator_type; 12 struct hogehoge_iterator_type; 13 14 using iterator = template_iterator<normal_iterator_type>; 15 using hoge_iterator = template_iterator<hoge_iterator_type>; 16 using hogehoge_iterator = template_iterator<hogehoge_iterator_type>; 17 18 // イテレータ取得関数 19 iterator begin() { return iterator(); } 20 hoge_iterator begin_hoge() { return hoge_iterator(); } 21 hogehoge_iterator begin_hogehoge() { return hogehoge_iterator(); } 22 23 template <typename iterator_type> struct template_iterator 24 { 25 // 共通の処理 26 void shared_func() 27 { 28 std::cout << "template_iterator::shared_func()" << '\n'; 29 } 30 31 // 個別の処理 32 void individual_func() 33 { 34 individual_func_obj<iterator_type>()(); 35 } 36 37 private: 38 /** 39 * 個別処理用関数オブジェクト 40 */ 41 template <typename itr_type, typename = void> struct individual_func_obj 42 { 43 void operator()(); 44 }; 45 }; 46}; 47 48/** 49* 関数オブジェクトの部分特殊化 50*/ 51template <typename T> 52template <typename iterator_type> 53template <typename V> 54struct container<T>::template_iterator<iterator_type>::individual_func_obj<typename container<T>::normal_iterator_type, V> 55{ 56 void operator()() { std::cout << "iterator::individual_func()" << '\n'; } 57}; 58 59template <typename T> 60template <typename iterator_type> 61template <typename V> 62struct container<T>::template_iterator<iterator_type>::individual_func_obj<typename container<T>::hoge_iterator_type, V> 63{ 64 void operator()() { std::cout << "hoge_iterator_type::individual_func()" << '\n'; } 65}; 66 67template <typename T> 68template <typename iterator_type> 69template <typename V> 70struct container<T>::template_iterator<iterator_type>::individual_func_obj<typename container<T>::hogehoge_iterator_type, V> 71{ 72 void operator()() { std::cout << "hogehoge_iterator_type::individual_func()" << '\n'; } 73}; 74 75int main(int argc, char const *argv[]) { 76 77 container<int> ctn; 78 auto itr = ctn.begin(); 79 auto itr_hoge = ctn.begin_hoge(); 80 auto itr_hogehoge = ctn.begin_hogehoge(); 81 82 itr.shared_func(); 83 itr_hoge.shared_func(); 84 itr_hogehoge.shared_func(); 85 itr.individual_func(); 86 itr_hoge.individual_func(); 87 itr_hogehoge.individual_func(); 88 89 return 0; 90} 91

投稿2017/05/11 23:06

yama_da

総合スコア73

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

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

0

こんにちは。

細かいところは見てないので、気がついた点だけ。

struct normal_iterator_type;

struct hoge_iterator_type;
struct hogehoge_iterator_type;

は、前方参照宣言なのでnormal_iterator_typeなどは「不完全型(incomplete type)」です。
以下のように完全型として定義すればinvalid use of incomplete typeエラーは消えると思います。

struct normal_iterator_type {};

struct hoge_iterator_type {};
struct hogehoge_iterator_type {};

投稿2017/05/06 04:31

Chironian

総合スコア23272

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

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

yama_da

2017/05/08 22:55

回答ありがとうございます。 試してみましたが、invalid use of incomplete typeエラーは消えませんでした。 悩んでても先に進まないので、以前の方法(基点クラスを作って派生)でとりあえず良しとしました。 また何かあればよろしくお願いします。
yama_da

2017/05/11 23:04

おはようございます。 そうだったんですね、できるもんだと思い込んでいました。 http://mimosa-pudica.net/cpp-specialization.html こちらのサイトを参考にしたら、なんとかいけました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問