[英]Specialization of function for a specific template type
Consider the following: 考虑以下:
template <typename TResult> inline TResult _from_string(const string& str);
template <> inline unsigned long long _from_string<unsigned long long>(const string& str) {
return stoull(str);
}
I can call the function as such: 我可以这样调用该函数:
auto x = _from_string<unsigned long long>("12345");
Now I would like to write another specialization for vector
s, ie: 现在,我想为
vector
编写另一种专门化,即:
template <typename T> inline vector<T> _from_string<vector<T>>(const string& str) {
// stuff that should be done only if the template parameter if a vector of something
}
so that I can do something like this: 这样我就可以做这样的事情:
auto x = _from_string<vector<int>>("{1,2,3,4,5}");
However, when I compile the function (under MSVC 2015), I get error C2768: "illegal use of explicit template arguments", which makes some sense as I shouldn't be having new template arguments in a specialization. 但是,当我编译该函数(在MSVC 2015下)时,出现错误C2768:“非法使用显式模板参数”,这是有道理的,因为我不应该在专业化中使用新的模板参数。
How can I rewrite the vector
specialization so that it will work? 如何重写
vector
专门化使其起作用?
Function templates can only be full specialized , they can't be partial specialized ; 功能模板只能是完全专业的 ,不能是部分专业的 ; but class templates can.
但是类模板可以。
// primary class template
template <typename T>
struct X {
static T _from_string(const string& str);
};
// full specialization for unsigned long long
template <>
struct X<unsigned long long> {
static unsigned long long _from_string(const string& str) {
return stoull(str);
}
};
// partial specialization for vector<T>
template <typename T>
struct X<vector<T>> {
static vector<T> _from_string(const string& str) {
// stuff that should be done only if the template parameter if a vector of something
}
};
// helper function template
template <typename TResult>
inline TResult _from_string(const string& str) {
return X<TResult>::_from_string(str);
}
then 然后
auto x1 = _from_string<unsigned long long>("12345");
auto x2 = _from_string<vector<int>>("{1,2,3,4,5}");
You cannot partially specialize functions. 您不能部分专门化功能。
You should rarely fully specialize functions. 您很少应该完全专门化功能。
A far better way to handle this problem is to use overloading. 处理此问题的一种更好的方法是使用重载。 Overloading on return type just requires an extra arg:
返回类型的重载仅需要一个额外的arg:
template<class T> struct tag_t{constexpr tag_t(){}; using type=T;};
template<class T>constexpr tag_t<T> tag{};
template <typename TResult> inline TResult _from_string(const string& str){
return _from_string( tag<TResult>, str );
}
Now we never specialize _from_string
, we just overload the 2 arg version. 现在,我们不再专门使用
_from_string
,我们只重载了2 arg版本。
inline unsigned long long _from_string(tag_t<unsigned long long>, const string& str) {
return stoull(str);
}
The above isn't even a template. 以上甚至都不是模板。
template <class T, class A>
std::vector<T,A> _from_string(tag_t<std::vector<T,A>>, const string& str) {
// stuff that should be done only if the target type is a vector of something
}
The above is a template, but not a specialization of one. 以上是一个模板,但不是一个专门的模板。
As a bonus, if you have a custom type bob
in namespace foo
, you simply have to write _from_string( tag_t<bob>, std::string const& )
in namespace foo
, and something known as 'ADL' will automatically find it in most cases. 作为奖励,如果你有一个自定义类型
bob
在namespace foo
,你只需要编写_from_string( tag_t<bob>, std::string const& )
在namespace foo
,和一些被称为“ADL”会自动找到它最案件。
Overload based dispatching with tags is clear and simple and lets you customize things in related namespaces. 使用标签进行的基于重载的分派非常简单明了,可让您自定义相关命名空间中的内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.