模板类是否可以用作模板函数专用化的参数
Can a template class be used as argument to a template function specialization?
我有以下模板函数:
template <class T>
inline T ParseValueFromJson(const JSONValue& jsonValue);
这反过来又用于其他模板函数,例如:
template <class T>
bool TryGetValueFromJson(
const JSONValue& jsonValue,
const String& name,
T& variable)
{
if (!jsonValue.Contains(name))
{
return false;
}
variable = ParseValueFromJson<T>(jsonValue[name]);
return true;
}
现在我想将 ParseValueFromJson 专门用于许多不同的类型,其中之一是模板类 (Vector)。但是,使用典型的专用化意味着 Vector 的类型参数将未定义:
template <>
inline Vector<T> ParseValueFromJson<Vector<T>>(const JSONValue& jsonValue)
除此之外,在函数实现中,我需要 T 的类型,因为我将使用 ParseValueFromJson 的 T 类型版本来解析单个项目。
当然,如果我在专业化中使用模板 T,它是一个不同的函数,会导致不明确的调用:
template <typename T>
inline Vector<T> ParseValueFromJson<Vector<T>>(const JSONValue& jsonValue)
那么这是可能的,还是我需要满足于一个单独的 TryGetContainerFromJson(或类似)函数,该函数将模板化集合类型作为第二个模板参数?
我会选择处理序列化的serializer
模板结构的实现(并且可以很容易地部分专业化),因为模板函数专用化可能很麻烦。
// Default serializer implementation.
namespace impl
{
template <typename T>
struct serializer
{
T from_json(const JSONValue& jv)
{
// default implementation...
}
};
}
// Convenient interface function.
template <class T>
inline T ParseValueFromJson(const JSONValue& jsonValue)
{
return impl::serializer<T>{}.from_json(jsonValue);
}
// "Special" serializer implementations.
namespace impl
{
template <typename T>
struct serializer<Vector<T>>
{
Vector<T> from_json(const JSONValue& jv)
{
Vector<T> result;
for(auto c : jv.children())
{
result.add(ParseValueFromJson<T>(c));
}
return result;
}
};
}
<</div>
div class="answers"> 您不能部分专用化函数模板(指向 Herb Sutter 的强制性链接),但您始终可以重载函数模板。只需沿着主节点前进,将类型作为标记参数传递:
template <class > struct tag { };
template <class T>
inline T ParseValueFromJson(const JSONValue& jsonValue) {
return impl::ParseValueFromJson(jsonValue, tag<T>{});
}
然后提供一堆重载:
namespace impl {
template <class T>
inline T ParseValueFromJson(const JSONValue& jsonValue, tag<T> ) {
// generic, if that makes sense
}
template <class T>
inline T ParseValueFromJson(const JSONValue& jsonValue, tag<std::vector<T>> ) {
// vector version
}
// etc.
}
您不能部分专用化函数,但是您当然可以重载它,包括使用另一个模板化函数。这有效:
template <typename T>
void func(const T& arg)
{
std::cout << "General" << std::endl;
}
template <typename T>
void func(const std::vector<T>& vec)
{
std::cout << "Vector overload" << std::endl;
}
int main()
{
func(1); //outputs "General"
func(std::vector<int>{1}); //outputs "Vector overload"
return 0;
}
在您的情况下,如果您愿意按输出参数返回,您可以调整此解决方案,因此您有 2 个这样的函数:
template <class T>
inline void ParseValueFromJson(const JSONValue& jsonValue, T& output);
template <class T>
inline void ParseValueFromJson(const JSONValue& jsonValue, std::vector<T>& output);
这实际上适用于您的代码,因为您最终已经通过输出参数返回答案。因此,在您的呼叫站点,您只需更改线路即可
variable = ParseValueFromJson<T>(jsonValue[name]);
自
ParseValueFromJson<T>(jsonValue[name], variable);
相关文章:
- 具有常量引用参数的函数模板专用化
- 通过依赖类型使用非类型模板参数的单类型模板参数类模板的部分专用化
- 具有多个参数的模板化类专用化,其中一个模板参数是模板本身
- 具有可变参数非类型参数的模板专用化
- 类专用化,没有用作专用化模板参数的类的模板参数
- 基于枚举参数调用专用模板方法
- 检查类是否具有模板专用化(使用布尔值或 int 等模板参数)
- 专用于可变参数模板成员函数
- 如何将模板类专用化为也接受模板模板参数
- 调用模板专用化,具有更多参数的单参数模板调用的特定值
- 有没有办法根据 lambda 参数返回类型部分专用化我的模板化函数?
- C++ 将派生类的成员函数指针作为参数传递时选择了错误的模板专用化
- cpp 模板专用化,错误说参数 1 的类型为 T,这取决于参数 T
- 具有不同非类型模板参数的模板类部分专用化
- 带有void类型和参数的C++11模板专用化
- 类模板专用化演绎是否应该考虑演绎指南参数初始化?
- 使用模板模板参数进行模板定义的函数专用化
- 在模板专用化中使用非类型模板模板参数
- C++具有可变参数专用参数的模板,用于参数数量
- 具有专用参数的类方法