我有一个变体类,它使用一些函数模板专门化来获取和设置使用Visual Studio 2010编译和工作的不同类型。但是这个代码位于一个通用的解决方案,它还需要在redhat,ubuntu等上编译
我收到了非命名空间范围内显式特化的错误。我认为简单的解决方法是简单地在类外定义我的特化,并在同一名称空间中使用范围限定符。
但是现在我得到的错误是在实例化之后发生了特化,因为类的其他方法用于从各种类型转换,在类中使用此模板。
那么做这样的事情的正确方法是什么:
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 :(得分: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);
}
}