C++ 模板特化除一种之外的所有类型

问题描述 投票:0回答:3

我需要一个为除一种类型之外的所有类型调用的方法(C++ 11)。

template<typename T>
void method(T& value)
{
...
}

template<>
void method(std::string& value)
{
...
}

可以做这样的事情吗?如果没有,除了在运行时使用 typeid 之外还有其他选择吗?

c++ c++11 templates
3个回答
7
投票

有多种方法可以执行此操作,因此您可以使用最方便的一种:

// 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 则用于过滤某些类型的子集


6
投票

您不需要模板专门化。也没有 SFINAE (

enable_if
)。当您陷入模板函数中时,很容易忘记函数可以重载。只需创建一个非模板化重载,当传递该精确类型的参数时,这将是首选(链接文章中提供了更好的解决方案):

template<typename T>
void method(T& value)
{
  // ...
}

void method(std::string& value)
{
  // ...
}

我强烈建议阅读 Herb Sutter 的这篇文章 为什么不专门化函数模板?

寓意#1:如果你想自定义一个函数基础模板并且想要 该定制参与重载决策(或者, 总是在完全匹配的情况下使用),使其成为普通的旧版本 功能,而不是专业。而且,如果你确实提供了重载, 避免同时提供专业化。

但是你陷入了道德#2:

但是如果您正在编写函数而不仅仅是使用函数呢? 模板?你能做得更好并避免这个(和其他)问题吗 为了你自己和你的用户?事实上你可以:

道德#2:如果您正在编写函数基础模板,更喜欢 将其编写为一个不应该的单一函数模板 专门化或重载,然后实现函数模板 完全作为到包含静态的类模板的简单切换 具有相同签名的函数。每个人都可以专攻这一点——两者 完全和部分,且不影响过载结果 分辨率。

完整解释在文章中。


0
投票

这是基本的模板专业化,请查看下面的代码示例。

代码示例(基于您的代码):

template<typename T>
void method(T& value) {
    //
}

template<>
void method<std::string>(std::string& value) {
    //
}

这意味着,当您使用 std::string 参数调用方法时,将调用第二个(专用)方法。否则,如果您不想拥有第二个功能,那么您将不得不使用 c++ 类型特征(在另一个答案中回答)。

© www.soinside.com 2019 - 2024. All rights reserved.