C++ 重载泛型类型的函数vs重载给定类型及其子类型的函数
我正在尝试编写一对重载函数,其中一个必须为指向不是B或B的子类型的指针调用,第二个必须为指向B和B的子类型的指针调用。首先,我尝试对B使用模板的专门化,但这对B的派生类不起作用。因此我查找了SFINAE和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):
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)
{couttypename 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::coutis_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
和重载(请参见示例)。