2016-02-11 159 views
0

尝试写例外模板构造函数类,因此抛出异常的时候,我可以把可变长度参数,来到某事像这样:模板的构造

namespace miniReader{ 

    namespace Exception{ 

     template<typename deriverEx, typename baseType> 
     class Exception : public baseType{ 
      std::string errorClass; 
      mutable std::string exStrMsg; 
     protected: 
      static std::stringstream exMsg; 
      std::string whatMessage; 
      // Exception(const Exception& other): baseType(""){} 

      const char* what() const noexcept{ 
       if(exStrMsg.empty()){ 
        exStrMsg = exMsg.str(); 
       } 
       exMsg.str(""); 
       return exStrMsg.c_str(); 
      } 

      ~Exception() noexcept { 
      } 
     public: 
      Exception(): baseType("") { 
      } 
     }; 

     class miniRuntimeException : public Exception<miniRuntimeException, std::runtime_error>{ 
     public: 
      miniRuntimeException(): Exception() {} 

      template<typename T, typename...Args> 
      miniRuntimeException(T first, Args...arg): Exception(){ 
       LOG(first, this); 
       exMsg << first << " "; 
       miniRuntimeException(arg...); 
      } 
     }; 

    template<typename deriverEx, typename baseType> 
    std::stringstream Exception<deriverEx, baseType>::exMsg; 

    } 
} 

现在我可以写抛出异常这样的:

miniRuntimeException(__FILE__, __LINE__, "Failed opening file", "Runtime Exception") 

我已经做了exMsg静态,因为在其他情况下,我可以得到所有的模板参数。所以我的问题是,Exception类中的exMsg是静态的,所以当派生类构造函数被调用时(variadic模板),读取参数是正确的。我找不到一种方法使它不是静态的,因为exMsg只会得到一个模板参数。有没有办法做到这一点?接下来的问题是当我的模板构造函数被调用时,为每个参数创建新对象(是否正确?)以及如何在这种情况下我可以在这些对象之间传递信息,如更新exMsg,因此它将在最终对象中完成?

+0

你的问题一般不是很清楚...... – callyalater

回答

0

我想我理解了这个问题(在阅读3次后)。我建议用下面的代码替换构造的链(继承被遗漏的,为了清楚起见):

class miniException { 
    std::stringstream msg; 
public: 
    template<class... ARGS> miniException(ARGS... args) { 
     populate_msg(args...); 
    } 
private: 
    template<class T, class... ARGS> void populate_msg(T t, ARGS... args) { 
     msg << t << " "; 
     populate_msg(args...); 
    } 
}; 
void populate_msg() { } 

P.S.你可能实际上想通过const引用而不是一个值来接受参数。

+0

谢谢,这就是工作。想知道为什么Exception类需要显式拷贝构造函数:* Exception(const Exception&other):baseType(“”){LOG(“Copy constructor”);} *然而它永远不会被调用,并且当它没有提供时,我会收到错误:*错误:使用已删除的函数'std :: __ cxx11 :: basic_stringstream <_CharT,_Traits,_Alloc> :: basic_stringstream(const std :: __ cxx11 :: basic_stringstream <_CharT,_Traits,_Alloc>&)[with _CharT = char; _Traits = std :: char_traits ; _Alloc = std :: allocator ] *谢谢 – user3655463

+0

因为'std :: basic_stringstream'确实有一个复制构造函数被声明为已删除。被调用或不被调用并不重要,因为编译器会为您的异​​常类生成升级副本。实际上你应该将你的定义定义为删除,而不是创建一个虚拟的。 – SergeyA

+0

感谢您的回复,想勾选您的回答有用,但没有足够的声誉不幸。 – user3655463