C++ *nix上的模板方法专门化
我有一个variant类,它使用一些函数模板专门化来获取和设置不同的类型,这些类型在VisualStudio2010中编译并运行良好。然而,这段代码位于一个公共解决方案中,该解决方案也需要在redhat、ubuntu等平台上编译 我在非命名空间范围内收到了一个关于显式专门化的错误。我认为简单的解决方法是在类之外定义我的专门化,并在同一名称空间中使用类的范围限定符 然而,现在我得到的错误是,由于用于从各种类型转换的类的其他方法正在类中使用此模板,所以在实例化之后会发生专门化 那么,这样做的正确方法是什么:C++ *nix上的模板方法专门化,c++,linux,templates,gcc,C++,Linux,Templates,Gcc,我有一个variant类,它使用一些函数模板专门化来获取和设置不同的类型,这些类型在VisualStudio2010中编译并运行良好。然而,这段代码位于一个公共解决方案中,该解决方案也需要在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;
}
}
名称空间示例
{
类CSomeVariant
{
公众:
bool-toString(标准::字符串和输出)
{
退换货;
}
私人:
模板
布尔盖特(T&val)
{
试一试{
val=boost::任意_转换(存储的m_);
}
捕获(…){
返回false;
}
返回true;
}
boost::存储的任何m_;
};
模板
boolcsomevariant::get(std::string&val)
{
试一试{
if(m_存储的.type()!=typeid(std::string))
val=convertToString();
其他的
val=boost::任意_转换(存储的m_);
}
捕获(…){
返回false;
}
返回true;
}
}
注意:这不是实际的代码,但我相信它表明了问题所在。问题在于您在类定义中使用了
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);
}
}
#包括
#包括
名称空间示例
{
类CSomeVariant
{
公众:
bool-toString(std::string&out);
私人:
模板
布尔盖特(T&val)
{
试一试{
val=boost::任意_转换(存储的m_);
}
捕获(…){
返回false;
}
返回true;
}
boost::存储的任何m_;
};
模板
boolcsomevariant::get(std::string&val)
{
试一试{
if(m_存储的.type()!=typeid(std::string))
val=convertToString();
其他的
val=boost::任意_转换(存储的m_);
}
捕获(…){
返回false;
}
返回true;
}
内联boolcsomevariant::toString(std::string&out)
{
退换货;
}
}
奇怪,看起来应该行得通……你为什么用专业化而不是?@ildjarn嗯,因为。。。说得好。哇,我现在觉得自己很笨。你比我快了1分钟!我刚刚在我刚到的高级C++元编程副本中读到过这篇文章。这篇文章有很多内容,但这是可行的。我同意ildjarn的建议,因为我喜欢完全取消专门化。@AJG85作为一般规则,我尽量避免专门化函数,并尽可能使用重载。规则更容易遵守。