* nix

2012-05-03 30 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作为一般规则,我尽量避免使用特殊函数,并尽可能使用重载。规则更容易遵循。 –