Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 重载泛型类型的函数vs重载给定类型及其子类型的函数_C++_Templates_C++11_Sfinae_Typetraits - Fatal编程技术网

C++ 重载泛型类型的函数vs重载给定类型及其子类型的函数

C++ 重载泛型类型的函数vs重载给定类型及其子类型的函数,c++,templates,c++11,sfinae,typetraits,C++,Templates,C++11,Sfinae,Typetraits,我正在尝试编写一对重载函数,其中一个必须为指向不是B或B的子类型的指针调用,第二个必须为指向B和B的子类型的指针调用。首先,我尝试对B使用模板的专门化,但这对B的派生类不起作用。因此我查找了SFINAE和enable_if等,但无法使其起作用 泛型函数的签名是 (1) 模板int f(T*T) 对于另一个,我尝试使用启用,如果和是的基础,如下所示: (2) template int f(typename enable_if::type*t) 但总是(1)被呼叫。我试图用否定(2)来代替(1):

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

泛型函数的签名是

(1)
模板int f(T*T)

对于另一个,我尝试使用
启用,如果
的基础,如下所示:

(2)
template int f(typename enable_if::type*t)

但总是(1)被呼叫。我试图用否定(2)来代替(1):

(1b)
template int f(typename enable_if::value,T>::type*T)

现在我得到了所有T的错误,不管它们是否是B的(孩子)

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

测试代码如下:

#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;
}
#包括
#包括
使用名称空间std;
B类{};
D类:公共B{};
C类{};
// (1)
/*模板
整数f(T*T)
{cout::type*t)

{cout将SFINAE移动到我们可以使用的模板参数中

// if not B or a descendant
template<typename T, typename enable_if<!is_base_of<B, T>::value>::type* = nullptr>
void f(T *t)
{ cout << "T\n"; }

// only if B or a descendant
template<typename T, typename enable_if<is_base_of<B, T>::value>::type* = nullptr>
void f(T *t)
{ cout << "B\n"; }
我们得到

B
B
T


由于您没有任何返回语句,我还将函数设置为void函数。

将SFINAE移动到我们可以使用的模板参数中

// if not B or a descendant
template<typename T, typename enable_if<!is_base_of<B, T>::value>::type* = nullptr>
void f(T *t)
{ cout << "T\n"; }

// only if B or a descendant
template<typename T, typename enable_if<is_base_of<B, T>::value>::type* = nullptr>
void f(T *t)
{ cout << "B\n"; }
我们得到

B
B
T

由于没有任何返回语句,我还将函数设为无效函数。

typename enable\u如果::value,T>::type
不可推断,则必须显式调用:

f<B>(&b);    // Want B;
f<D>(&d);    // Want B;
f<C>(&c);    // Want T;
f&b);//想要b;
f(&d);//想要B;
f(&c);//想要T;

为了便于推断,您可以使用SFINAE的一种经典方式:返回类型

// (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"; }
//(1b)
样板
如果\u t::value>
f(T*T)
{cout::value>*=nullptr>
空隙f(T*T)
{cout
typename enable_如果::value,T>::type
是不可推断的,那么您必须显式调用:

f<B>(&b);    // Want B;
f<D>(&d);    // Want B;
f<C>(&c);    // Want T;
f&b);//想要b;
f(&d);//想要B;
f(&c);//想要T;

为了便于推断,您可以使用SFINAE的一种经典方式:返回类型

// (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"; }
//(1b)
样板
如果\u t::value>
f(T*T)
{cout::value>*=nullptr>
空隙f(T*T)

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

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);
}
模板
void fImpl(T*T,const void*){

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

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);
}
模板
void fImpl(T*T,const void*){

std::cout
is_base\u of::value,T>::type
不会神奇地推断
T
并将其用作
type
is_base\u of::value,T>::type
不会神奇地推断
T
并将其用作
type
。谢谢,这很有效!但是有没有办法让它在没有默认模板参数的情况下工作吗?我的解决方案需要在c++11之前的版本中,我使用的是
的变体是
的基础,如果
则是
的启用,但现在它会在默认模板参数上呕吐。@chengiz我不确定。当我使用SFINAE时,这是我最舒服的方式。我仍在学习它。谢谢,这很有效!但是有没有办法让它在没有默认模板的情况下工作呢论据?我的解决方案还需要在c++11之前的版本上工作,在c++11之前,我使用了
is_base_of
enable_if
的变体,但现在它会在默认模板参数上呕吐。@chengiz我不确定。当我使用SFINAE时,这是我最舒服的方式。我还在学习它。很好。这可能对OP最好,因为它们实际上是不要使用C++11Genius!对我来说非常适合。您甚至可以简化它,同时依赖于
静态转换和重载(参见示例).Nice。这可能对OP最好,因为他们实际上没有C++11Genius!对我来说非常适合。您甚至可以简化它,同时依赖于
static\u cast
和重载(请参见示例)。