C++模板特殊化所有类型,除了一个

s6fujrry  于 2024-01-09  发布在  其他
关注(0)|答案(3)|浏览(116)

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

  1. template<typename T>
  2. void method(T& value)
  3. {
  4. ...
  5. }
  6. template<>
  7. void method(std::string& value)
  8. {
  9. ...
  10. }

字符串
有没有可能这样做?如果没有,除了在运行时使用typeid,还有其他的选择吗?

zzzyeukh

zzzyeukh1#

有几种方法可以做到这一点,所以你可以使用最方便的一个:

  1. // way 1
  2. template<typename T,
  3. typename std::enable_if<!std::is_same<T,std::string>::value>::type* = nullptr>
  4. // way 2
  5. void method(T& value)
  6. {
  7. static_assert(!std::is_same<T,std::string>::value,"std::string is not accepted");
  8. ...
  9. }
  10. // way 3
  11. template <>
  12. void method<std::string>(std::string&) = delete;

字符串
对我来说,我发现3是过滤特定类型最方便的一个,1是过滤一些类型子集的一个

展开查看全部
iyzzxitl

iyzzxitl2#

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

  1. template<typename T>
  2. void method(T& value)
  3. {
  4. // ...
  5. }
  6. void method(std::string& value)
  7. {
  8. // ...
  9. }

字符串
我强烈推荐阅读这篇文章Why Not Specialize Function Templates?由赫伯萨特。
寓意一:如果你想自定义一个函数基模板,并希望该自定义参与重载解析(或者,总是在精确匹配的情况下使用),让它成为一个普通的旧函数,而不是一个专门化。而且,如果你确实提供了重载,避免同时提供专门化。
但你落入了道德二:
但是如果你是一个编写函数模板的人,而不仅仅是使用函数模板呢?你能做得更好,为你自己和你的用户预先避免这个(和其他)问题吗?事实上,你可以:
寓意二:如果你在写一个函数基模板,更喜欢把它写成一个单独的函数模板,不应该被特殊化或重载,然后把函数模板完全实现成一个简单的传递给一个包含具有相同签名的静态函数的类模板。每个人都可以特殊化它--完全或部分地,而不影响重载解析的结果。
整个解释都在文章里。

展开查看全部
o2g1uqev

o2g1uqev3#

这是基本的模板专门化,看看下面的代码示例。
代码示例(基于您的代码):

  1. template<typename T>
  2. void method(T& value) {
  3. //
  4. }
  5. template<>
  6. void method<std::string>(std::string& value) {
  7. //
  8. }

字符串
这意味着,当你调用带有std::string参数的方法时,第二个(专用的)方法将被调用。否则,如果你不想有第二个函数,那么你将不得不使用c++类型traits(在另一个答案中回答)。

相关问题