C++ C++;模板专门化除一个之外的所有类型

C++ C++;模板专门化除一个之外的所有类型,c++,c++11,templates,C++,C++11,Templates,我需要一个方法(C++11),除了一个之外,它可以调用所有类型 template<typename T> void method(T& value) { ... } template<> void method(std::string& value) { ... } 模板 无效方法(T和值) { ... } 模板 void方法(标准::字符串和值) { ... } 有可能这样做吗?如果没有,除了在运行时使用typeid,还有其他选择吗?有几种方法可以

我需要一个方法(C++11),除了一个之外,它可以调用所有类型

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

template<>
void method(std::string& value)
{
...
}
模板
无效方法(T和值)
{
...
}
模板
void方法(标准::字符串和值)
{
...
}

有可能这样做吗?如果没有,除了在运行时使用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; 
//方法1
模板::类型*=nullptr>
//方式2
无效方法(T和值)
{
静态断言(!std::is_same::value,“std::string不被接受”);
...
}
//方式3
模板
void方法(std::string&)=delete;

对于我来说,我发现3是筛选特定类型最方便的方法,1是筛选某些类型子集最方便的方法

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

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

模板
无效方法(T和值){
//
}
模板
void方法(标准::字符串和值){
//
}

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

< P>你不需要模板特化。和两个SFINAE(
如果
,则启用)。当您被模板函数所困扰时,很容易忘记函数可能会过载。只需创建一个非模板重载,当传递一个确切类型的参数时,它将被优先考虑(链接文章中提供了一个更好的解决方案):

模板
无效方法(T和值)
{
// ...
}
void方法(标准::字符串和值)
{
// ...
}

我强烈推荐阅读Herb Sutter的这篇文章

寓意#1:如果你想定制一个函数基模板 参与重载解析的自定义项(或 始终在精确匹配的情况下使用),使其成为普通的旧版本 功能,而不是专门化。如果您提供了重载, 避免提供专业化

但你却陷入了道德2:

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

寓意2:如果您正在编写函数基模板,更喜欢 将其作为一个函数模板编写,而不应 专门化或重载,然后实现函数模板 完全作为一个简单的切换到包含静态 具有相同签名的函数。每个人都可以专攻这两个领域 全部和部分,且不影响过载结果 决议


整个解释都在这篇文章中。

这与只针对一种类型进行专门化有什么不同?您展示的解决方案有什么问题?谷歌搜索“模板专门化”没有给出您需要的答案吗?若否,原因为何?你已经做到了。对于除
string
之外的所有类型,都将使用主模板。如果主模板适用于该类型,为什么不直接使用呢?对于gcc-6和cmcstl2,您还可以使用概念。如果s@Maikel,是的,我知道,但也会很冗长:
需要!std::is_same::value
如果想要重载函数,而不是删除它,那么普通重载比专门化要好。但有时使用普通重载是不够的(处理类型组、值类别、隐式可转换类型等)@AndreiR。如果您想删除它,那么您只需
=delete
。如果您需要类型组等,那么是的,这是不够的。请记住,当尝试专门化具有相同衰退类型的类型时,重载可能会导致问题。在尝试专门化char*、const char*、char[]、const char[]、string literal、std::string和const std::string时,不可能不引起歧义
template<typename T>
void method(T& value) {
    //
}

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

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