質問編集履歴
5
追記
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
追記
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\(\)が不要だったので削除
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修正と説明文の修正
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
|
-
こんなに複雑なことをしている目的は
|
67
|
+
こんなに複雑なことをしている目的は、Lib<>のインスタンスで使われているTypeのリストをvalueと関連づけて、Lib<>のコンストラクタ内で取り出せるようにすることです。
|
67
68
|
```C++
|
68
69
|
// lib.h
|
69
70
|
#include <iostream>
|
1
説明の補足
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
|
-
//
|
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
|
-
|
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>
|