| 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 | } |