teratail header banner
teratail header banner
質問するログイン新規登録

質問編集履歴

5

追記

2016/12/22 03:09

投稿

Chironian
Chironian

スコア23274

title CHANGED
File without changes
body CHANGED
@@ -1,4 +1,8 @@
1
1
  【追記】不可能な内容かも知れないのですが、まだ少しだけ希望を持っていますので、「解決済」には致しません。もし、解をお持ちの方がいらっしゃいましたら、是非ご教授下さい。
2
+
3
+ 【2016/12/22追記】
4
+ 長らく放置してしまいました。断念したのでクローズします。
5
+
2
6
  ---
3
7
 
4
8
  今、あるライブラリをC++11準拠の条件で開発してます。

4

追記

2016/12/22 03:09

投稿

Chironian
Chironian

スコア23274

title CHANGED
File without changes
body CHANGED
@@ -1,3 +1,6 @@
1
+ 【追記】不可能な内容かも知れないのですが、まだ少しだけ希望を持っていますので、「解決済」には致しません。もし、解をお持ちの方がいらっしゃいましたら、是非ご教授下さい。
2
+ ---
3
+
1
4
  今、あるライブラリをC++11準拠の条件で開発してます。
2
5
  コンパイラは、msvc 2015とg++4.9.2以降を想定しています。
3
6
 

3

getValue\(\)が不要だったので削除

2015/11/18 05:33

投稿

Chironian
Chironian

スコア23274

title CHANGED
File without changes
body CHANGED
@@ -77,7 +77,6 @@
77
77
  class BaseSingleton
78
78
  {
79
79
  public:
80
- virtual int getValue() = 0;
81
80
  virtual void print(int aValue) = 0;
82
81
  };
83
82
 
@@ -101,7 +100,6 @@
101
100
  return instance;
102
101
  }
103
102
 
104
- int getValue() {return value;}
105
103
  void print(int aValue)
106
104
  {
107
105
  if (aValue == value)

2

typo修正と説明文の修正

2015/11/12 03:25

投稿

Chironian
Chironian

スコア23274

title CHANGED
File without changes
body CHANGED
@@ -5,7 +5,7 @@
5
5
  Client()関数の中身が結構大きくなりそうなので、できればClient()関数をテンプレートではなく通常の関数にしたいのです。
6
6
 
7
7
  このような場合、通常はLib<>クラスを基底クラスから派生するようにし、Func()関数を仮想関数にすると思います。しかし、関数テンプレートを仮想関数にすることができませんので、Client()を非テンプレート化できないのです。
8
- 仮想関数にわる何か良い方法はないでしょうか?
8
+ 仮想関数にわる何か良い方法はないでしょうか?
9
9
 
10
10
  Typeには制限を付けられませんが、valueはあまり無茶に増えることはないので、現時点ではClient()を関数テンプレートのままとし、使用するvalueについて明示的実体化することで考えています。
11
11
  しかし、もし、方法があればClient()を通常の関数で開発できるようにしたいのです。
@@ -63,7 +63,8 @@
63
63
  boostで使われているテクニックですが、シングルトン生成時、スタティック変数Instanceをこのように初期化することで、main()関数が走る前にこのシングルトンが生成されます。
64
64
  これにより、Lib<>のコンストラクタで、Lib<>::Func()に渡されるTypeの型リストへアクセスできるようになるのです。
65
65
  このタイミングではLib<>がコンストラクトされていないので、動的な方法ではvalueをリストできないのです。
66
+
66
- こんなに複雑なことをしている目的はこのLib<>のンストラクタで使われているTypeのリストを取り出すことです。
67
+ こんなに複雑なことをしている目的はLib<>のンスタンスで使われているTypeのリストをvalueと関連づけて、Lib<>のコンストラクタ内で取り出せるようにことです。
67
68
  ```C++
68
69
  // lib.h
69
70
  #include <iostream>

1

説明の補足

2015/11/12 02:26

投稿

Chironian
Chironian

スコア23274

title CHANGED
File without changes
body CHANGED
@@ -23,7 +23,116 @@
23
23
  void Func(const Type& aInstance)
24
24
  {
25
25
  std::cout << value << " :" << typeid(aInstance).name() << "\n";
26
+ // 実際にはここで下記シングルトンを生成しています
27
+ // template<typename Type, int value>
28
+ // class Singleton {};
29
+ }
30
+ };
31
+ ```
32
+ ```C++
33
+ // main.cpp
34
+ #include "lib.h"
35
+
36
+ class Foo {};
37
+
38
+ template<int value>
39
+ void Client(Lib<value>* aLib)
40
+ {
41
+ aLib->Func(123);
42
+ aLib->Func(123.0);
43
+ aLib->Func(Foo());
44
+ }
45
+
46
+ int main()
47
+ {
48
+ Lib<456> lib_456;
49
+ Lib<789> lib_789;
50
+
51
+ Client(&lib_456);
52
+ Client(&lib_789);
53
+ }
54
+ ```
55
+
56
+ ---
57
+
58
+ 【追記】
59
+ サンプルの説明が不適切だったので、Func()内のコメントを修正しました。
60
+
61
+ また、何のためにSingleton<Type, value>を作っているのか分からないと思います。
62
+ かなり長くなってしまうのですか、実際に使っているものに近いサンプルを以下に示します。
63
+ boostで使われているテクニックですが、シングルトン生成時、スタティック変数Instanceをこのように初期化することで、main()関数が走る前にこのシングルトンが生成されます。
64
+ これにより、Lib<>のコンストラクタで、Lib<>::Func()に渡されるTypeの型リストへアクセスできるようになるのです。
65
+ このタイミングではLib<>がコンストラクトされていないので、動的な方法ではvalueをリストできないのです。
66
+ こんなに複雑なことをしている目的はこのLib<>のコンストラクタで使われているTypeのリストを取り出すことです。
67
+ ```C++
68
+ // lib.h
69
+ #include <iostream>
70
+ #include <typeinfo>
71
+ #include <vector>
72
+
73
+ class BaseSingleton;
74
+ std::vector<BaseSingleton*> TypeList;
75
+
76
+ class BaseSingleton
77
+ {
78
+ public:
79
+ virtual int getValue() = 0;
80
+ virtual void print(int aValue) = 0;
81
+ };
82
+
83
+ template<typename Type, int value>
84
+ class Singleton : public BaseSingleton
85
+ {
86
+ private:
87
+ static Singleton& Instance;
88
+ Singleton()
89
+ {
90
+ std::cout << "Singleton() : " << value << " :" << typeid(Type).name() << "\n";
91
+ }
92
+ static void use(const Singleton&) {}
93
+
94
+ public:
95
+ static Singleton& getInstance()
96
+ {
97
+ static Singleton instance;
98
+ use(Instance);
99
+ TypeList.push_back(&instance);
100
+ return instance;
101
+ }
102
+
103
+ int getValue() {return value;}
104
+ void print(int aValue)
105
+ {
106
+ if (aValue == value)
107
+ std::cout << "print() : " << value << " :" << typeid(Type).name() << "\n";
108
+ }
109
+
110
+ // コピー/ムーブ禁止
111
+ Singleton(const Singleton&) = delete;
112
+ Singleton( Singleton&&) = delete;
113
+ Singleton& operator=(const Singleton&) = delete;
114
+ Singleton& operator=( Singleton&&) = delete;
115
+ };
116
+ template<typename Type, int value>
117
+ Singleton<Type, value>& Singleton<Type, value>::Instance = Singleton<Type, value>::getInstance();
118
+
119
+ template<int value>
120
+ struct Lib
121
+ {
122
+ Lib()
123
+ {
124
+ // ここで自分で使われている型のリストを抽出してます
125
+ for (auto& itr : TypeList) {
126
+ itr->print(value);
127
+ }
128
+ }
129
+
130
+ template<typename Type>
131
+ void Func(const Type& aInstance)
132
+ {
133
+ Singleton<Type, value>::getInstance();
134
+
26
- // 実際SFINAEを使ってTypeで分岐し、下記のようなイメージの処理をします
135
+ // にSFINAEを使ってTypeで分岐し、下記のようなイメージの処理をします
27
136
  // 組み込み型の時は特定の処理を行う
28
137
  // 関数bar()を持つclassなら、bar()を呼ぶ
29
138
  // 関数boo()を持つclassなら、boo()を呼ぶ
@@ -36,7 +145,6 @@
36
145
  #include "lib.h"
37
146
 
38
147
  class Foo {};
39
-
40
148
  template<int value>
41
149
  void Client(Lib<value>* aLib)
42
150
  {
@@ -45,12 +153,56 @@
45
153
  aLib->Func(Foo());
46
154
  }
47
155
 
156
+ class Bar {};
157
+ template<int value>
158
+ void Client2(Lib<value>* aLib)
159
+ {
160
+ aLib->Func("string");
161
+ aLib->Func(Bar());
162
+ }
163
+
48
164
  int main()
49
165
  {
166
+ std::cout << "---------- Start main()\n";
167
+
168
+ std::cout << "pre Lib<456>\n";
50
169
  Lib<456> lib_456;
170
+ std::cout << "post Lib<456>\n";
171
+ Client(&lib_456);
172
+
173
+ std::cout << "pre Lib<789>\n";
51
174
  Lib<789> lib_789;
175
+ std::cout << "post Lib<789>\n";
176
+ Client(&lib_789);
52
177
 
178
+ std::cout << "pre Lib<-123>\n";
179
+ Lib<-123> lib_m123;
180
+ std::cout << "post Lib<-123>\n";
53
- Client(&lib_456);
181
+ Client2(&lib_m123);
54
- Client(&lib_789);
55
182
  }
56
- ```
183
+ ```
184
+ msvc2015での実行結果は下記の通りです。
185
+
186
+ Singleton() : 456 :int
187
+ Singleton() : 456 :double
188
+ Singleton() : 456 :class Foo
189
+ Singleton() : 789 :int
190
+ Singleton() : 789 :double
191
+ Singleton() : 789 :class Foo
192
+ Singleton() : -123 :char [7]
193
+ Singleton() : -123 :class Bar
194
+ ---------- Start main()
195
+ pre Lib<456>
196
+ print() : 456 :int
197
+ print() : 456 :double
198
+ print() : 456 :class Foo
199
+ post Lib<456>
200
+ pre Lib<789>
201
+ print() : 789 :int
202
+ print() : 789 :double
203
+ print() : 789 :class Foo
204
+ post Lib<789>
205
+ pre Lib<-123>
206
+ print() : -123 :char [7]
207
+ print() : -123 :class Bar
208
+ post Lib<-123>