C++ 用模板专门化模板

C++ 用模板专门化模板,c++,templates,specialization,C++,Templates,Specialization,我有一个(免费)函数模板,看起来像这样 template <typename T> T get(); 模板 T get(); 现在我想为一个类专门化这个函数,这个类本身就是一个模板。但是我的编译器不想编译它,我现在想问的是这是否可能,以及我如何实现它。为了实现这个想法,代码可以如下所示:(不编译) 模板 模板 foo_类型get() 您所做的工作称为函数模板的部分专门化。但不允许函数模板的部分专门化。允许重载函数模板,但在这种情况下,也不可能重载,因为函数只有返回类型,并且不允许

我有一个(免费)函数模板,看起来像这样

template <typename T>
T get();
模板
T get();
现在我想为一个类专门化这个函数,这个类本身就是一个模板。但是我的编译器不想编译它,我现在想问的是这是否可能,以及我如何实现它。为了实现这个想法,代码可以如下所示:(不编译)

模板
模板
foo_类型get()

您所做的工作称为函数模板的部分专门化。但不允许函数模板的部分专门化。允许重载函数模板,但在这种情况下,也不可能重载,因为函数只有返回类型,并且不允许重载返回类型

因此,解决方案是:

namespace details
{
     template <typename T>
     struct worker
     {
         static T get();
     };

     template <typename T> //partial specialization of class is allowed
     struct worker<foo<T>>
     {
         static foo<T> get();
     };

}

template <typename T>
T get()
{
  return details::worker<T>::get();
}
名称空间详细信息
{
模板
结构工人
{
静态T get();
};
模板//允许类的部分专门化
结构工人
{
静态foo-get();
};
}
模板
不明白
{
返回详细信息::worker::get();
}

如果您将重载定义为接受一个参数以使重载有效,也可以使用重载:

namespace details
{
     template <typename T>
     static T get(T*); 

     template <typename T> 
     static foo<T> get(foo<T>*); //now the overload is valid

}

template <typename T>
T get()
{
  return details::get<T>(static_cast<T*>(0));
}
名称空间详细信息
{
模板
静态T-get(T*);
模板
静态foo-get(foo*);//现在重载有效
}
模板
不明白
{
返回详细信息::get(static_cast(0));
}

请注意,参数
static\u cast(0)
用于帮助编译器选择正确的重载。如果
T
不是
foo
,则将选择第一个重载,因为传递给它的参数类型将是
T*
,而不是
foo*
。如果
T
foo
,那么编译器将选择第二个重载,因为它更专业,在这种情况下可以接受传递给它的参数
foo*

正如纳瓦兹所说,标准不允许您这样做。但是,您可以将实现提取到类的静态方法中,并部分地专门化该类

template<class T>
struct get_impl{
  static T get(){ ... }
};

template<class T>
struct get_impl<foo_type<T> >{
  static foo_type<T> get(){ ... }
};

template<class T>
T get(){ return get_impl<T>::get(); }
模板
结构get\u impl{
静态T get(){…}
};
模板
结构get\u impl{
静态foo_类型get(){…}
};
模板
T get(){return get_impl::get();}

现在,看到解决方案,这是显而易见的。非常感谢。但现在我得到一个链接器错误。。有什么想法吗?@Xeo:哦。对你说得对。当我发布它的时候,我觉得我做错了什么,但我无法理解。@cooky:你把模板函数体放在了.cpp中了吗?:)不,链接错误是在重载函数时出现的。有点可笑,别问我编译器在那里做了什么。(不是很明显,他只是把他的任务委托给了链接者;)--不过,这现在行得通了,谢谢你们,现在我必须决定接受什么作为答案。也许我可以掷骰子静态_强制转换(nullptr)
template<class T>
struct get_impl{
  static T get(){ ... }
};

template<class T>
struct get_impl<foo_type<T> >{
  static foo_type<T> get(){ ... }
};

template<class T>
T get(){ return get_impl<T>::get(); }