* nix

2012-05-03 29 views
4

上的模板方法專業化我有一個變體類,它使用一些函數模板專業化來獲取和設置不同的類型,這些類型在Visual Studio 2010中編譯和運行良好。但是,此代碼位於同樣需要編譯的通用解決方案中在RedHat,Ubuntu的等* nix

我收到了一個錯誤沿着非命名空間範圍顯式專業化的行。我認爲簡單的解決方法是簡單地在類的外部使用範圍限定符在同一名稱空間中爲類定義我的特化。

但是現在我得到了實例化後發生的特化錯誤,因爲從各種類型轉換而來的類的其他方法在類中使用此模板。

那麼什麼是做這樣的事情的正確方法:

namespace Example 
{ 
    class CSomeVariant 
    { 
    public: 
     bool toString(std::string& out) 
     { 
      return get(out); 
     } 
    private: 
     template <typename T> 
     bool get(T& val) 
     { 
      try { 
       val = boost::any_cast<T>(m_stored); 
      } 
      catch (...) { 
       return false; 
      } 
      return true; 
     } 

     boost::any m_stored; 
    }; 

    template<> 
    bool CSomeVariant::get(std::string& val) 
    { 
     try { 
      if (m_stored.type() != typeid(std::string)) 
       val = convertToString(); 
      else 
       val = boost::any_cast<std::string>(m_stored); 
     } 
     catch(...) { 
      return false; 
     } 
     return true; 
    } 
} 

注:這是不實際的代碼,但我相信它顯示的問題。

+0

奇怪,看起來像應該工作... – Benj

+3

爲什麼你使用專業化而不是[簡單重載](http://ideone.com/W1KYE)? – ildjarn

+0

@ildjarn嗯,因爲...好點。哇,我現在覺得很愚蠢。 – AJG85

回答

3

問題是,您在類定義中使用了get()函數,然後再進行專門化,這是不允許的。從14.7.3條第6款

如果一個模板,一個成員模板或類模板的成員 明確專門那麼專業化應在第一次使用的是專業化的前宣佈 會導致 隱在 的每個翻譯單元中發生這種使用的實例化;不需要診斷。如果程序 未提供明確專業化的定義,或者專業化的使用方式會導致發生隱式實例化或成員是虛擬成員 函數,則該程序是格式不正確的,不需要診斷。

一個解決方案是對類定義進行重新排序,以便在任何使用之前聲明特化。在這種情況下,我能夠將該函數的內聯使用移至專業化之後。

#include <string> 
#include <boost/any.hpp> 
namespace Example 
{ 
    class CSomeVariant 
    { 
    public: 
     bool toString(std::string& out); 

    private: 
     template <typename T> 
     bool get(T& val) 
     { 
      try { 
       val = boost::any_cast<T>(m_stored); 
      } 
      catch (...) { 
       return false; 
      } 
      return true; 
     } 

     boost::any m_stored; 
    }; 

    template<> 
    bool CSomeVariant::get(std::string& val) 
    { 
     try { 
      if (m_stored.type() != typeid(std::string)) 
       val = convertToString(); 
      else 
       val = boost::any_cast<std::string>(m_stored); 
     } 
     catch(...) { 
      return false; 
     } 
     return true; 
    } 


    inline bool CSomeVariant::toString(std::string& out) 
    { 
     return get(out); 
    } 
} 
+0

你打我1分鐘!我剛剛在新到的Advanced C++ MetaProgramming副本中閱讀了這篇文章。 – TemplateRex

+0

有很多toThis或toThat方法,但這將工作。我打算用ildjarn的建議去做,因爲我喜歡完全消除專業化。 – AJG85

+3

@ AJG85作爲一般規則,我儘量避免使用特殊函數,並儘可能使用重載。規則更容易遵循。 –