简体   繁体   English

特定模板类型的功能专业化

[英]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}");

LIVE 生活

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. 作为奖励,如果你有一个自定义类型bobnamespace 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM