特定模板类型

时间:2017-01-14 07:18:08

标签: c++ templates specialization

请考虑以下事项:

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);
}

我可以这样调用函数:

auto x = _from_string<unsigned long long>("12345");

现在我想为vector s编写另一个专门化,即:

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
}

这样我就可以这样做:

 auto x = _from_string<vector<int>>("{1,2,3,4,5}");

然而,当我编译该函数时(在MSVC 2015下),我得到错误C2768:&#34;非法使用显式模板参数&#34;,这有点意义,因为我不应该有新模板专业化中的论据。

如何重写vector专业化以使其有效?

2 个答案:

答案 0 :(得分:3)

功能模板只能是full specialized,不能是partial specialized;但类模板可以。

// 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);
}

然后

auto x1 = _from_string<unsigned long long>("12345");
auto x2 = _from_string<vector<int>>("{1,2,3,4,5}");

LIVE

答案 1 :(得分:3)

你不能部分专门化功能。

你应该很少完全专门化功能。

处理此问题的一个更好的方法是使用重载。在返回类型上重载只需要一个额外的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 );
}

现在我们从不专门化_from_string,我们只是重载了2个arg版本。

inline unsigned long long _from_string(tag_t<unsigned long long>, const string& str) {
  return stoull(str);
}

以上甚至不是模板。

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
}

上面是一个模板,但不是一个专门化。

作为奖励,如果您在bob中拥有自定义类型namespace foo,则只需在_from_string( tag_t<bob>, std::string const& )中写一个namespace foo,并将其称为&#39; ADL&#39;在大多数情况下会自动找到它。

使用标记进行基于重载的调度非常简单,并且允许您自定义相关命名空间中的内容。