首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >重载泛型类型的函数和给定类型及其子类型的函数

重载泛型类型的函数和给定类型及其子类型的函数
EN

Stack Overflow用户
提问于 2016-06-02 16:29:42
回答 2查看 67关注 0票数 1

我正在尝试编写一对重载函数,一个必须被调用的指向非B或B的子类型的指针,第二个必须被调用为指向B的指针和B的子函数。首先,我尝试为B使用模板的专门化,但这不适用于派生的B类,所以我查找了SFINAE和enable_if等,但是无法让它工作。

泛型函数的签名是

(1) template<typename T> int f(T *t)

另一方面,我试图像这样使用enable_ifis_base_of

(2) template<typename T> int f(typename enable_if<is_base_of<B, T>::value, T>::type *t)

但总是(1)被调用。我试图将(1)改为否定(2):

(1b) template<typename T> int f(typename enable_if<!is_base_of<B, T>::value, T>::type *t)

现在,我得到了所有Ts的错误,不管它们是否为B的子女。

我做错了什么?解决办法是什么?

测试代码如下:

代码语言:javascript
复制
#include <type_traits>
#include <iostream>

using namespace std;

class B {};
class D : public B {};
class C {};

// (1)
/* template<typename T>
int f(T *t)
{ cout << "T\n"; } */

// (1b)
template<typename T>
int f(typename enable_if<!is_base_of<B, T>::value, T>::type *t)
{ cout << "T\n"; }

// (2)
template<typename T>
int f(typename enable_if<is_base_of<B, T>::value, T>::type *t)
{ cout << "B\n"; }

int main()
{
  B b;
  D d;
  C c;
  f(&b);    // Want B; get T with (1), dont compile with (1b)
  f(&d);    // Want B; get T with (1), dont compile with (1b)
  f(&c);    // Want T; get T with (1), dont compile with (1b)
  return 0;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-06-02 17:10:46

一个非常简单的解决方法是再次传递指针作为第二个函数参数,用于区分这两个版本。

代码语言:javascript
复制
template<typename T>
void fImpl(T* t, const void*) { 
   std::cout << "general";
}

template<typename T>
void fImpl(T *b, const B*) {
   std::cout << "specific";
}

template<typename T>
void f(T *t) { 
   fImpl(t, t);
}
票数 2
EN

Stack Overflow用户

发布于 2016-06-02 17:06:26

typename enable_if<!is_base_of<B, T>::value, T>::type是不可还原的,因此您必须显式调用:

代码语言:javascript
复制
f<B>(&b);    // Want B;
f<D>(&d);    // Want B;
f<C>(&c);    // Want T;

演示

为了简化,您可以使用SFINAE的一种经典方法:返回类型。

代码语言:javascript
复制
// (1b)
template<typename T>
enable_if_t<!is_base_of<B, T>::value>
f(T* t)
{ cout << "T\n"; }

// (2)
template<typename T>
enable_if_t<is_base_of<B, T>::value>
f(T* t)
{ cout << "B\n"; }

演示

或作为模板参数:

代码语言:javascript
复制
// (1b)
template<typename T, enable_if_t<!is_base_of<B, T>::value>* = nullptr>
void f(T* t)
{ cout << "T\n"; }

// (2)
template<typename T, enable_if_t<is_base_of<B, T>::value>* = nullptr>
void f(T* t)
{ cout << "B\n"; }

演示

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37597357

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档