ä¾å¤ã¨ã¨ã©ã¼ãã¾ãã¾ãã§ããã©ã¤ãã©ãª xreturn ãä½ã£ã¦ã¿ãã
ãã㯠C++11 Advent Calendar 2011 ã®è¨äºã§ãã
ãæè¦ãææ³ã¯ããã¡ãã¾ã§ãæ°è»½ã«ã»ã»ã»ããããã³ã¼ãã®ããã«è°è«ãããã§ãã
ãªããå°ãåã«ãã¨ã©ã¼å¦çãæ¸ãã¦ã¯ãããªãã¨ããè¨äºãã§ã¦ãã¾ã£ã¦ãé常ã«å°ã£ãæããªã®ã§ãããã¨ã©ã¼ãã³ããªã³ã°ã®ã¯ãªãããã¾ãwwww
ã ã£ã¦ããããããã¿ãªããã§ããããã
ä»æ¹ãªããããä»æ¹ãªãã§ããããããã¯ãããããããªãã§ãããã
ä¾å¤ã¨ã¨ã©ã¼ã®è©±ãã¯ããã¨ãã¦
ä¾å¤ã¨ã¨ã©ã¼ã¯éããã
ããããä½ãæã£ã¦ä¾å¤ã§ãä½ãæã£ã¦ã¨ã©ã¼ãã¨ããã®ã¯ã使ãå ´åã«ããã¨ããã®ãçãã«ãªãã§ãããã
(詳細ãæ¸ãã¨ããããªãã®ã§ã次åã®åå¼·ä¼ã¨ãã§è°è«ãã¾ãããï¼ï¼ï¼ï¼)
ã§ã
ä¾å¤ã¨ã¨ã©ã¼ãã¾ãã¾ããã¦ã·ã³ãã«ã«æ¸ãããã
ã¡ãã£ã¨åã«ä¾å¤ã¨ã¨ã©ã¼ãã¾ãããã«ãã¦ã·ã³ãã«ã«è¨è¿°ã§ããã©ã¤ãã©ãªãä½ãã¾ããã
ã§ãä»åã¯ãããã¤ãããããå¤æ´ãã¾ãã£ã¦ãã¯ã¼ã¢ããããã¦ã¿ã¾ããã
ã½ã¼ã¹ã¯githubã«ãããã
VC++10 㨠gcc 4.6.1ã§åä½ç¢ºèªããã¦ãã¾ããC++11 ãå©ç¨ã§ããã°å¤§ä¸å¤«ã§ãã
ãããªé¢¨ã«æ¸ãã¾ãã
//fizzbuzz ã®å¤åå½¢ã«åºä¼ãã¨ã¨ã©ã¼ã«ãªãã¾ãã //ãã以å¤ã¯å ¥åããå¤ã帰ãã¾ãã xreturn::r<int> fizzbuzz(int a) { if (((a % 3) == 0) && ((a % 5) == 0)) { return xreturn::error("3ã¨5ã§å²ãåãã¾ãããª",35); //ã¨ã©ã¼ã«ããã } if ((a % 3) == 0) { return xreturn::error("3ã§å²ãåãã¾ãããª",3); //ã¨ã©ã¼ã«ããã } if ((a % 5) == 0) { return xreturn::error("5ã§å²ãåãã¾ãããª",5); //ã¨ã©ã¼ã«ããã } return a; }
使ãå´ã¯ãããããªä½¿ãæ¹ãã§ãã¾ãã
æ¢åã®æ¸ãæ¹ã«åãããã¨ãããªæãã§ãã
ãµã¤ã¼ã§ããï¼
int a1 = fizzbuzz(1); std::cout << a1 << std::endl; //1ã帰ã
ãããã¨ã©ã¼ãçºçããçµã¿åãããå¼ãã§ãããã§ä½ããããã¨ããã¨ããã£ã¹ãããç¬éã«ä¾å¤ãé£ãã§ããã¾ãã
int a3 = fizzbuzz(3); //ä¾å¤ xreturn::error("3ã§å²ãåãã¾ãããª",3); ãé£ã¶ã
ã¨ã©ã¼ãç¡è¦ãããã¨ãã¦ãåæ§ã§ãã(ååããã®ãã¯ã¼ã¢ãã)
printf ã fseekã¿ããã«å¼ã¶ãã¨ã«æ義ãããé¢æ°ã§ãå¹ççã«æ¸ãã¾ããã
fizzbuzz(1); //ä½ãèµ·ããªã fizzbuzz(3); //ä¾å¤ xreturn::error("3ã§å²ãåãã¾ãããª",3); ãé£ã¶ã
ãããããåæã«ä¾å¤ãé£ã°ãã¦ããããå°ããã
åã¯ã¨ã©ã¼ãã³ããªã³ã°ããã£ã¡ãããããã ãã£ã¦äººã®éè¦ãæºããã¾ãã
auto r1 = fizzbuzz(1); //1ãªã®ã§æ£ããå¦ççµæã帰ãã¾ãã if (r1.isOK()) { //é常ã®å¦çãã³ã³ã«æ¸ãã¾ãããã } auto r3 = fizzbuzz(3); //3ã§å²ãåããã®ã§ã¨ã©ã¼ã«ãªãã¾ãã if (r3.isError()) { //ã¨ã©ã¼å¦çãæ¸ãã¾ãã }
autoã§ãã¡ãã¡åããã¨ãããµããªãï¼ã£ã¦äººã大ä¸å¤«ã§ãã
if (!fizzbuzz(3)) { //ã¨ã©ã¼å¦çãæ¸ãã¾ãã }
ã¨ã©ã¼ã³ã¼ãã§åå²ãããããã ãã©ã£ã¦äººã大ä¸å¤«ã
auto r3 = fizzbuzz(3); if (!r3) { if ( r3.getErrorCode() == 3 ) { } else if ( r3.getErrorCode() == 3 ) { } else if ( r3.getErrorCode() == 35 ) { } }
ã¨ã©ã¼ã³ã¼ãã¨ãããµããªãï¼åã§ã¨ã©ã¼ã表ç¾ããã®ãä»ã®ãã¬ã³ããªãã ãã£ã£ã¦äººããå®å¿ãã
(ååããã®ãã¯ã¼ã¢ãã)
class error_fizz : public xreturn::error { public: error_fizz(){} error_fizz(const std::string & message , int code) : xreturn::error(message,code){} virtual ~error_fizz(){} }; class error_buzz : public xreturn::error { public: error_buzz(){} error_buzz(const std::string & message , int code) : xreturn::error(message,code){} virtual ~error_buzz(){} }; class error_fizzbuzz : public xreturn::error { public: error_fizzbuzz(){} error_fizzbuzz(const std::string & message , int code) : xreturn::error(message,code){} virtual ~error_fizzbuzz(){} }; xreturn::r<int,error_fizz,error_buzz,error_fizzbuzz> fizzbuzz_for_type(int a) { if (((a % 3) == 0) && ((a % 5) == 0)) { return error_fizzbuzz("3ã¨5ã§å²ãåãã¾ãããª",35); } if ((a % 3) == 0) { return error_fizz("3ã§å²ãåãã¾ãããª",3); } if ((a % 5) == 0) { return error_buzz("5ã§å²ãåãã¾ãããª",5); } return a; } //使ãå´ã¯ããããªãµãã«æ¸ãã¾ãã //C++ã®switchæãããã¡ãã£ã¨è³¢ããªãã¨ãã£ã¨ããæãã«ã§ãããããããªããã auto z3 = fizzbuzz_for_type(3); if (z3.type() == typeid(int) ) //if (!z3) ã z3.isOK() ã¨åãæå³ã§ãã { std::cout << z3 << std::endl; //3ã帰ãããä»åã¯ã¨ã©ã¼ãªã®ã§ã³ã³ã«ã¯æ¥ãªã MY_ASSERT(0); } else if (z3.type() == typeid(error_fizz) ) { std::cout << "fizz" << std::endl; } else if (z3.type() == typeid(error_buzz) ) { std::cout << "buzz" << std::endl; MY_ASSERT(0); //ä»åã¯3 fizzãªã®ã§ããã«ã¯ããªã } else if (z3.type() == typeid(error_fizzbuzz) ) { std::cout << "fizzbuzz" << std::endl; MY_ASSERT(0); //ä»åã¯3 fizzãªã®ã§ããã«ã¯ããªã }
ã¨ããããããããªæãã§ãã
é常ã®æ£å¸¸ç³»ã®å¦çã®æµããéªéããã«ããã¤ã¨ã©ã¼å¦çãæè»ã«æ¸ãã¾ãã
é¢æ°ãå¼ã³åºãå´ã§å¶å¾¡ã§ããã®ã§ããä½ãæã£ã¦ä¾å¤ãï¼ããã¯å ´åã«ããããã¨ãã£ãåé¡ã«å¯¾å¿ã§ãã¾ãã
使ãæ¹ã¯ï¼
ãã¡ããããããã¼ãã¡ã¤ã« xreturn.h ã include ããã ãã§å©ç¨ã§ãã¾ãã
ç°¡åã§ããã
ã§ãã³ã¹ããããããã§ããï¼
10,000,000åå¼ã³åºãã¦ã5åãããã®å·®ãã§ã¾ãã
5åã¨ãã£ã¦ãã109ããªç§ç¨åº¦ã§ããã»ã»ã»ã
ããã¯ãã¨ã©ã¼ãæ¡ãã¤ã¶ãã¦ããªããã確èªãããã©ã°ç®¡çã«æ¯æã£ã¦ããã³ã¹ãã ã¨æããã¾ãã
ãã³ããã¼ã¯ 10000000åå¼ã³åºãã¾ã éxreturn: 31ms xreturn: 140ms
å®è£ ãè¦ããã¨ãªã»ã»ã»
å®è£
ã¯ãããªæãã§ãã
é·ãã§ãããgithubãè¦ãã»ããããããããªã¤ã«ã
#pragma once #include <string> #include <typeinfo> // //æ»ãå¤ã«ã¨ã©ã¼ã絡ã¾ããããããã«ãã¦ã¿ãã©ã¤ãã©ãª // // namespace xreturn { //ã¨ã©ã¼ã³ã¼ã㨠std::string ããããããã«ããä¾å¤ã¯ã©ã¹ //xreturn::error ã¨ãã¦ä½¿ã£ã¦ãã class error : public std::exception { protected: std::string message; // int code; //std::exceptionããªããä¿æãã¦ãããªãã®ã§èªåã§ä¿æãã. public: error() { } error(const std::string & message , int code) : std::exception() { this->message = message; this->code = code; } virtual ~error() throw() { } virtual int getErrorCode() const { return this->code; } virtual std::string getErrorMessage() const { return this->message; } virtual const char* what() const throw() { return this->message.c_str(); } }; //ãã³ãã¬ã¼ãã®åã§é¢æ°ä½ãããã¨ãã«åãåã ã¨è¡çªãã¦æ»ã¬ã®ã§åé¿ãã. class dummy_error2 : public xreturn::error{}; class dummy_error3 : public xreturn::error{}; class dummy_error4 : public xreturn::error{}; class dummy_error5 : public xreturn::error{}; class dummy_error6 : public xreturn::error{}; class dummy_error7 : public xreturn::error{}; class dummy_error8 : public xreturn::error{}; //ä¾å¤ããæ´¾çãã¦ããåãæ ¼ç´ãã class any_error_base { public: virtual void throwException() const = 0; virtual const xreturn::error& get() const = 0; virtual const std::type_info& type() const = 0; virtual ~any_error_base(){} }; template<typename ERRORTYPE> class any_error : public any_error_base { ERRORTYPE error; public: any_error(const ERRORTYPE & e) : any_error_base() { this->error = e; } virtual ~any_error() { } virtual void throwException() const { throw this->error; } virtual const xreturn::error& get() const { return this->error; } virtual const std::type_info& type() const { return typeid(ERRORTYPE); } const ERRORTYPE& getError() const { return &this->error; } }; //ã¨ã©ã¼ãã©ããããæ§é template <typename TYPE ,typename ERRORTYPE1 = xreturn::error ,typename ERRORTYPE2 = dummy_error2 ,typename ERRORTYPE3 = dummy_error3 ,typename ERRORTYPE4 = dummy_error4 ,typename ERRORTYPE5 = dummy_error5 ,typename ERRORTYPE6 = dummy_error6 ,typename ERRORTYPE7 = dummy_error7 ,typename ERRORTYPE8 = dummy_error8 > class r { private: TYPE value; any_error_base* error; mutable bool nigirichubushi; //ãã¾ã¬ã»ã»ã» const auto ã«å¯¾å¿ããããã«ã mutableã«ããã¦ããã public: r() { this->error = nullptr; this->nigirichubushi = false; } virtual ~r() { if (this->nigirichubushi) { //é常ã«æ©ã¾ããããããã¦ãã¹ãã©ã¯ã¿ã§ä¾å¤ãæããã //ã¨ã©ã¼ããã§ãã¯ããªãã§æ¡ãã¤ã¶ããããªã³ã¼ãã§ä¾å¤å¦çãè¡ãã«ã¯ããããæ¹æ³ããªãããã if ( this->isError() ) { //deleteã§æ¶ãçµãã£ã¦ãããthrow exception ããããã ãã©ã æããä¾å¤ãæ¶ãããã¡ã¢ãªç©ºéã«ããããã§ã»ã»ã» //ããã¯ãããã«ãã¸ã£ã³ã¯ã³ã¼ããããã®ã§ãªãã¨ãããããã ãã©ã if ( typeid(ERRORTYPE1) == this->error->type() ) { auto e = *(dynamic_cast< any_error<ERRORTYPE1>* >(this->error)); delete this->error; this->error = nullptr; e.throwException(); } if ( typeid(ERRORTYPE2) == this->error->type() ) { auto e = *(dynamic_cast< any_error<ERRORTYPE2>* >(this->error)); delete this->error; this->error = nullptr; e.throwException(); } if ( typeid(ERRORTYPE3) == this->error->type() ) { auto e = *(dynamic_cast< any_error<ERRORTYPE3>* >(this->error)); delete this->error; this->error = nullptr; e.throwException(); } if ( typeid(ERRORTYPE4) == this->error->type() ) { auto e = *(dynamic_cast< any_error<ERRORTYPE4>* >(this->error)); delete this->error; this->error = nullptr; e.throwException(); } if ( typeid(ERRORTYPE5) == this->error->type() ) { auto e = *(dynamic_cast< any_error<ERRORTYPE5>* >(this->error)); delete this->error; this->error = nullptr; e.throwException(); } if ( typeid(ERRORTYPE6) == this->error->type() ) { auto e = *(dynamic_cast< any_error<ERRORTYPE6>* >(this->error)); delete this->error; this->error = nullptr; e.throwException(); } if ( typeid(ERRORTYPE7) == this->error->type() ) { auto e = *(dynamic_cast< any_error<ERRORTYPE7>* >(this->error)); delete this->error; this->error = nullptr; e.throwException(); } if ( typeid(ERRORTYPE8) == this->error->type() ) { auto e = *(dynamic_cast< any_error<ERRORTYPE8>* >(this->error)); delete this->error; this->error = nullptr; e.throwException(); } } } delete this->error; this->error = nullptr; } //boolã«ãã£ã¹ãããå ´å //ããã§å®è£ ããã¨ã xreturn::r<bool> ã®æã«è¡çªãããã operator ã§éãã. // operator bool() // { // this->nigirichubushi = false; // return this->isOK(); // } bool operator !() const { return this->isError(); } bool operator ==(bool t) const { if ( typeid(TYPE) == typeid(bool) ) {//xreturn::r<bool>ã®å ´åã¯å¤å¥ä¸è½ãªã®ã§æ®éã«ãã£ã¹ã operator TYPE() ã«é£ã°ã. return (*this); } return (t == true && this->isOK()) || (t == false && this->isOK()); } operator TYPE() const { this->nigirichubushi = false; if ( this->isError() ) { this->error->throwException(); //ããã§ä¾å¤ãæãã } return this->value; } r<TYPE>& operator =(const TYPE & a) { this->value = a; this->error = nullptr; this->nigirichubushi = false; a.nigirichubushi = false; return *this; } r(const TYPE& a) { this->value = a; this->error = nullptr; this->nigirichubushi = false; } r(const ERRORTYPE1& e) { this->error = new any_error<ERRORTYPE1>(e); this->nigirichubushi = true; } r(const ERRORTYPE2& e) { this->error = new any_error<ERRORTYPE2>(e); this->nigirichubushi = true; } r(const ERRORTYPE3& e) { this->error = new any_error<ERRORTYPE3>(e); this->nigirichubushi = true; } r(const ERRORTYPE4& e) { this->error = new any_error<ERRORTYPE4>(e); this->nigirichubushi = true; } r(const ERRORTYPE5& e) { this->error = new any_error<ERRORTYPE5>(e); this->nigirichubushi = true; } r(const ERRORTYPE6& e) { this->error = new any_error<ERRORTYPE6>(e); this->nigirichubushi = true; } r(const ERRORTYPE7& e) { this->error = new any_error<ERRORTYPE7>(e); this->nigirichubushi = true; } r(const ERRORTYPE8& e) { this->error = new any_error<ERRORTYPE8>(e); this->nigirichubushi = true; } bool isOK() const { this->nigirichubushi = false; //ãã¾ã¬ã»ã»ã» const auto ã«å¯¾å¿ããããã«ã mutableã«ããã¦ããã return this->error == nullptr; } bool isError() const { this->nigirichubushi = false; return this->error != nullptr; } TYPE check() const { this->nigirichubushi = false; return (*this); } const any_error_base* getError() const { //ASSERT(this->error != nullptr); this->nigirichubushi = false; return this->error; } int getErrorCode() const { return this->getError()->get().getErrorCode(); } std::string getErrorMessage() const { return this->getError()->get().getErrorMessage(); } //ä¾å¤ãæãã. void throwException() const { this->nigirichubushi = false; this->error->throwException(); } //ç¾ç¶ã®åæ å ±ãåå¾ãã const std::type_info& type() const { //æåãã¦ããå ´åã¯ãä¿æãã¦ããåããã®ã¾ã¾ if ( this->isOK() ) { return typeid(TYPE); } //ã¨ã©ã¼ã®å ´åã¯ãã¨ã©ã¼åãããã ã. return this->getError()->type(); } };
ã¡ãã£ãã¾www
ä½ï¼å®è£
ãããã¦ããªãã¨ãªï¼
mutable ãããã¯ä»¥å¤ã«ä½¿ã£ã¦ãããã ããããã¨ããã¹ãã©ã¯ã¿ã§ä¾å¤ãæãã¦ããªãã¦ãããã¯ç¦å¿ã®é åã§ã¯ãªããã
ã¨ã©ã¼ãã§ãã¯ãç¡è¦ãããå ´åã®å¯¾å¦ããããããæãã¤ããªãã£ããã ãã
fizzbuzz(1); //ä½ãèµ·ããªã fizzbuzz(3); //ä¾å¤ xreturn::error("3ã§å²ãåãã¾ãããª",3); ãé£ã¶ã(ããããããã)
ãã®ããã«æ»ãå¤ãç¡è¦ããã¦ãã¾ã£ãã¨ãã¯ã operator void ã¨ããå¼ã°ãããã§ããªããããããããã¯ããæ¹æ³ããã¹ãã©ã¯ã¿ãè¦ããã¨ä»¥å¤æãã¤ããªãã£ãã
ã ããããã¼ãã¼å®è£
ã«ãªã£ã¦ããã
ä¸å¿ãã¡ã¢ãªç®¡çã2éã®throw 対çãªã©ã¯æ°ã使ã£ã¦å
¥ããã»ã»ã»ã»
æ¥å:ããããªãã¨ãããæ¹æ³ãç¥ã£ã¦ãã人ã¯ãtwitterã¨ãã§æãã¦ãã ããã
ããã¾ãæ¬å½ã«æ³¨æãã¦ãããã ãããªã
ãã¦ã注æãã¦å
¥ãã¨ãã£ãããããã§ã 2éthrow ã«ãªã£ã¦ãã¾ãå ´åãããã®ã§ãã
ä¾ãã°ã以ä¸ã®ãããªã³ã¼ãã§ãã
auto r3_1 = fizzbuzz(3); auto r3_2 = fizzbuzz(3); int a = r3_2; //ããã§ä¾å¤ãã¹ã¿ãã¯å·»ãæ»ãããã®ã§ r3_1 ãä¾å¤ãå¼ã¶ã
ä¸å¿ãããã«å¯¾å¦ããæ¹æ³ã¨ãã¦ã¯ããã¨ã©ã¼ãã§ãã¯ã¯ã¾ã¨ãã¦ããã®ã§ã¯ãªãã¦ãä¸ã¤ã¥ã¤ããããã¨ããæ¹æ³ãããã¾ãã
//ä¸ã¤ã¥ã¤ãã int r3_1 = fizzbuzz(3); //ããã§ä¾å¤ int r3_2 = fizzbuzz(3);
//ä¸ã¤ã¥ã¤ãã auto r3_1 = fizzbuzz(3); //ããã§ä¾å¤ if (!r3_1) { } int r3_2 = fizzbuzz(3); if (!r3_1) { }
//ä¸ã¤ã¥ã¤ãã int r3_1 = fizzbuzz(3).check(); //ããã§ä¾å¤ if (!r3_1) { } int r3_2 = fizzbuzz(3).check(); if (!r3_1) { }
ã¾ã¼ã¤ã¾ãããµã¤ã¼ã«çµãã§ããéãã¯ã ã¾ã¨ãã¦ã¨ã©ã¼ãã§ãã¯ãã¦ããã«throw ã§æ»ã¬ãªãã¦ãã¨ã¯ãªããã¯ãããªãã ãã©ã»ã»ã»ã
æ°æã¡ããããã®ã§ã¯ãªãã®ã§ããªãã¨ãããããã
ä»ã¯ããã以ä¸ã®æ¹æ³ãæãã¤ããªããã©ãã
ã¾ã¨ã
ããä¸åº¦ xretrun ã使ã£ãã³ã¼ããè¦ã¦ã¿ããã
ãªããããã£ããããã¦ãï¼(èªç»èªè³)
xreturn::r<int,error_fizz,error_buzz,error_fizzbuzz> fizzbuzz_for_type(int a) { if (((a % 3) == 0) && ((a % 5) == 0)) { return error_fizzbuzz("3ã¨5ã§å²ãåãã¾ãããª",35); } if ((a % 3) == 0) { return error_fizz("3ã§å²ãåãã¾ãããª",3); } if ((a % 5) == 0) { return error_buzz("5ã§å²ãåãã¾ãããª",5); } return a; } //使ãå´ã¯ããããªãµãã«æ¸ãã¾ãã //C++ã®switchæãããã¡ãã£ã¨è³¢ããªãã¨ãã¿ã¼ã³ãããã¿ããã«ã§ãããããããªããã auto z3 = fizzbuzz_for_type(3); if (z3.type() == typeid(int) ) //if (!z3) ã z3.isOK() ã¨åãæå³ã§ãã { std::cout << z3 << std::endl; //3ã帰ãããä»åã¯ã¨ã©ã¼ãªã®ã§ã³ã³ã«ã¯æ¥ãªã MY_ASSERT(0); } else if (z3.type() == typeid(error_fizz) ) { std::cout << "fizz" << std::endl; } else if (z3.type() == typeid(error_buzz) ) { std::cout << "buzz" << std::endl; MY_ASSERT(0); //ä»åã¯3 fizzãªã®ã§ããã«ã¯ããªã } else if (z3.type() == typeid(error_fizzbuzz) ) { std::cout << "fizzbuzz" << std::endl; MY_ASSERT(0); //ä»åã¯3 fizzãªã®ã§ããã«ã¯ããªã }
ã¾ã¼ã xretrun 使ãã¨ãã¨ã©ã¼ãã·ã³ãã«ã«æ¸ããããããªãã®ï¼
å®è£
ã¯ä¸é¨ããã¦ããªãã¨ããã¯ãããã©ãã
ã¨ã©ã¼ã®ããã¨ãã(ãã³ããªã³ã°ãæè»)ãä¾å¤ã®ããã¨ãã(ç¡è¦ãããªããåºåé¢è±ãä»å æ
å ±)ã®ããã¨ãåãã§ããããããï¼
使ãå´ããããã»ã©è² è·ããããã«ä½¿ã人ã¯ã§ããããã©ã¤ãã©ãªãä½ãå´ããããã»ã©é£ããã¯ãªãã§ãããã
ããã¦ãä½ããããä½ãæã£ã¦ä¾å¤ãï¼ã£ã¦è°è«ã«çµæ¢ç¬¦ãæã¦ãããããªã¼ã
ããã¾ãã