我需要一个为除一种类型之外的所有类型调用的方法(C++ 11)。
template<typename T>
void method(T& value)
{
...
}
template<>
void method(std::string& value)
{
...
}
可以做这样的事情吗?如果没有,除了在运行时使用 typeid 之外还有其他选择吗?
有多种方法可以执行此操作,因此您可以使用最方便的一种:
// way 1
template<typename T,
typename std::enable_if<!std::is_same<T,std::string>::value>::type* = nullptr>
// way 2
void method(T& value)
{
static_assert(!std::is_same<T,std::string>::value,"std::string is not accepted");
...
}
// way 3
template <>
void method<std::string>(std::string&) = delete;
对于我来说,我发现 3 是过滤特定类型最方便的一种,而 1 则用于过滤某些类型的子集
您不需要模板专门化。也没有 SFINAE (
enable_if
)。当您陷入模板函数中时,很容易忘记函数可以重载。只需创建一个非模板化重载,当传递该精确类型的参数时,这将是首选(链接文章中提供了更好的解决方案):
template<typename T>
void method(T& value)
{
// ...
}
void method(std::string& value)
{
// ...
}
我强烈建议阅读 Herb Sutter 的这篇文章 为什么不专门化函数模板?。
寓意#1:如果你想自定义一个函数基础模板并且想要 该定制参与重载决策(或者, 总是在完全匹配的情况下使用),使其成为普通的旧版本 功能,而不是专业。而且,如果你确实提供了重载, 避免同时提供专业化。
但是你陷入了道德#2:
但是如果您正在编写函数而不仅仅是使用函数呢? 模板?你能做得更好并避免这个(和其他)问题吗 为了你自己和你的用户?事实上你可以:
道德#2:如果您正在编写函数基础模板,更喜欢 将其编写为一个不应该的单一函数模板 专门化或重载,然后实现函数模板 完全作为到包含静态的类模板的简单切换 具有相同签名的函数。每个人都可以专攻这一点——两者 完全和部分,且不影响过载结果 分辨率。
完整解释在文章中。
这是基本的模板专业化,请查看下面的代码示例。
代码示例(基于您的代码):
template<typename T>
void method(T& value) {
//
}
template<>
void method<std::string>(std::string& value) {
//
}
这意味着,当您使用 std::string 参数调用方法时,将调用第二个(专用)方法。否则,如果您不想拥有第二个功能,那么您将不得不使用 c++ 类型特征(在另一个答案中回答)。