Revision | 51709849704de6ba7dbee6554f50ff9cb45b1673 (tree) |
---|---|
Time | 2020-11-26 23:25:59 |
Author | dhrname <dhrname@user...> |
Commiter | dhrname |
New EXPECT for BDD
@@ -28,7 +28,27 @@ | ||
28 | 28 | |
29 | 29 | /*Nodeの抽象クラス |
30 | 30 | * 5方向リンクのリスト |
31 | - * これを型として使う。*/ | |
31 | + * これを型として使う。 | |
32 | + * | |
33 | + *使用例 | |
34 | + * Node* a = node<float>(1.0); | |
35 | + * a.appendChild(node<int>(1)); | |
36 | + * a.appendChild(node<std::string>("hoge")); | |
37 | + * | |
38 | + * while (a->isNode()) | |
39 | + * { | |
40 | + * if ( a->isCaseOf(typeid(int)) ) | |
41 | + * { | |
42 | + * int num = a->getValue(); | |
43 | + * } | |
44 | + * else if ( a->isCaseOf(typeid(std::string)) ) | |
45 | + * { | |
46 | + * std::string str = a->getValue(); | |
47 | + * } | |
48 | + * } | |
49 | + * なお、isCaseOfメンバ関数の名前の由来は、ダイクストラ、ホーア、ウィルトたちが、 | |
50 | + * 熟慮したうえで生み出したcase...of...文である。 | |
51 | + **/ | |
32 | 52 | class Node |
33 | 53 | { |
34 | 54 | public: |
@@ -52,6 +72,11 @@ public: | ||
52 | 72 | virtual Node* appendChild(Node* const) = 0; |
53 | 73 | |
54 | 74 | virtual bool isNode() = 0; |
75 | + | |
76 | + virtual bool isCaseOf(type_info&) = 0; | |
77 | + | |
78 | + /*getValueメンバ関数は、多重定義を想定しているので、必ずしもNode*となるとは限らない*/ | |
79 | + virtual Node* getValue() = 0; | |
55 | 80 | }; |
56 | 81 | |
57 | 82 | /*空のノードクラス*/ |
@@ -73,8 +98,14 @@ public: | ||
73 | 98 | Node* appendChild(Node*){return this;}; |
74 | 99 | bool isNode() |
75 | 100 | { |
76 | - return false; | |
77 | - } | |
101 | + return false; | |
102 | + }; | |
103 | + virtual bool isCaseOf(type_info& id) | |
104 | + { | |
105 | + return false; | |
106 | + }; | |
107 | + | |
108 | + virtual Node* getValue(){return this;}; | |
78 | 109 | }; |
79 | 110 | |
80 | 111 | EmptyNode* const emptynode = new EmptyNode(); |
@@ -83,7 +114,7 @@ EmptyNode* const emptynode = new EmptyNode(); | ||
83 | 114 | * Node抽象クラスに対する内部実装*/ |
84 | 115 | class BaseNode: public EmptyNode |
85 | 116 | { |
86 | -protected: | |
117 | +private: | |
87 | 118 | Node* parentNode; |
88 | 119 | Node* nextSibling; |
89 | 120 | Node* previousSibling; |
@@ -244,25 +275,38 @@ Node* BaseNode::removeChild(Node* const child) | ||
244 | 275 | |
245 | 276 | return child; |
246 | 277 | } |
278 | + | |
279 | +/*insertBefore メンバ関数 | |
280 | + * 子ノードのprevの前隣りに、nodeを挿入する | |
281 | + * 引数prevが空ノードであれば、親ノードに末子ノードとして登録される | |
282 | + *@param node | |
283 | + *@param prev | |
284 | + *@return 挿入されたnode | |
285 | + **/ | |
247 | 286 | Node* BaseNode::insertBefore(Node* const node, Node* const prev) |
248 | 287 | { |
249 | - this.throwArgumentError(node, "insertBefore"); | |
288 | + this->throwArgumentError(node, "insertBefore"); | |
250 | 289 | |
251 | - /*prevはemptynodeの可能性が含まれる*/ | |
252 | - this.throwNULLArgumentError(prev, "insertBefore"); | |
290 | + /*prevはemptynodeの可能性が含まれるので、throwArgumentErrorは使わない*/ | |
291 | + this->throwNULLArgumentError(prev, "insertBefore"); | |
253 | 292 | |
254 | - /*祖先ノードの中に、今挿入しつつあるnodeと一致するものがあれば、参照エラー | |
293 | + if (prev->getParent() != this) | |
294 | + { | |
295 | + throw std::invalid_argument("NotFoundError: prev is not child on the insertBefore"); | |
296 | + } | |
297 | + | |
298 | + /*祖先ノードの中に、今挿入しつつあるnodeと一致するものがあれば、階層の参照エラー | |
255 | 299 | * というのは、循環参照を引き起こすため*/ |
256 | 300 | Node* p = this; |
257 | 301 | |
258 | - while (p.isNode()) | |
302 | + while (p->isNode()) | |
259 | 303 | { |
260 | 304 | if (p == node) |
261 | 305 | { |
262 | - throw std::invalid_argument("Reference error on the insertBefore"); | |
306 | + throw std::invalid_argument("HierarchyRequestError on the insertBefore"); | |
263 | 307 | } |
264 | 308 | |
265 | - p = p->getParent(p); | |
309 | + p = p->getParent(); | |
266 | 310 | } |
267 | 311 | |
268 | 312 | Node* pnode = node->getParent(); |
@@ -312,13 +356,48 @@ Node* BaseNode::insertBefore(Node* const node, Node* const prev) | ||
312 | 356 | } |
313 | 357 | Node* BaseNode::appendChild(Node* const node) |
314 | 358 | { |
315 | - return this->parentNode; | |
359 | + return this->insertBefore(node, emptynode); | |
316 | 360 | } |
317 | 361 | |
362 | +template<typename T> | |
363 | +class node | |
364 | +{ | |
365 | +private: | |
366 | + T& nodeValue; | |
367 | + type_info valueType; | |
368 | + | |
369 | +public: | |
370 | + node(T& value) | |
371 | + : nodeValue(value), | |
372 | + valueType(typeid(T)) | |
373 | + {} | |
374 | + | |
375 | + bool isCaseOf(const type_info id) | |
376 | + { | |
377 | + if (valueType == id) | |
378 | + { | |
379 | + return true; | |
380 | + } | |
381 | + else | |
382 | + { | |
383 | + return false; | |
384 | + } | |
385 | + } | |
386 | + | |
387 | + T& getValue() | |
388 | + { | |
389 | + return nodeValue; | |
390 | + } | |
391 | +}; | |
392 | + | |
393 | +#define EXPECT(x, y) if((x)!=(y)){std::cout<<"line "<<__LINE__<<": EXPECT("<<(x)<<","<<(y)<<") on the file "<<__FILE__<<std::endl;} | |
394 | + | |
318 | 395 | int main(int argc, char **argv) |
319 | 396 | { |
320 | 397 | std::string str1 = "ABC"; |
321 | - std::cout << "A" << str1 << std::endl; | |
398 | + std::cout << "S" << str1 << std::endl; | |
399 | + EXPECT(0, 0); | |
400 | + EXPECT(0, 1); | |
322 | 401 | try |
323 | 402 | { |
324 | 403 | } |