gpt4 book ai didi

c++ - C++ 中的模板特化和派生类

转载 作者:IT老高 更新时间:2023-10-28 22:36:50 26 4
gpt4 key购买 nike

我有这个简单的代码:

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

class Test
{
public:
template<typename T>
void f(T&){printf("template\n");}
void f(A&){printf("specialization\n");}
};

int main()
{
A a;
B b;
C c;

Test test;
test.f(a);
test.f(b);
test.f(c);
}

当我运行它时(VS2010)我有这个输出:

specialization
template
template

是否可以使用 A-derived 类进行调用以使用特化?

最佳答案

是的,这是可能的,但您必须稍微更改您的代码。

首先,从技术上讲,第二个函数f() 不是模板函数的特化,而是重载 .解决重载时,为所有类型不是 A 的参数选择模板版本,因为它是完美匹配:T 被推断为等于参数,因此当调用 f(b) 时,例如,在类型推导之后,编译器将不得不在以下两个重载之间进行选择:

void f(B&){printf("template\n");}
void f(A&){printf("specialization\n");}

当然,第一个是更好的匹配。

现在,如果您希望在使用 A 子类的参数调用函数时选择第二个版本,则必须使用一些 SFINAE 技术来防止函数模板正确当类型 T 被推断为 A 的子类时实例化。

您可以将 std::enable_ifstd::is_base_of 类型特征结合使用来实现。

// This will get instantiated only for those T which are not derived from A
template<typename T,
typename enable_if<
!is_base_of<A, T>::value
>::type* = nullptr
>
void f(T&) { cout << "template" << endl; }

以下是在完整程序中使用它的方法:

#include <type_traits>
#include <iostream>

using namespace std;

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

class Test
{
public:

template<typename T,
typename enable_if<!is_base_of<A, T>::value>::type* = nullptr
>
void f(T&) { cout << ("template\n"); }

void f(A&){ cout << ("non-template\n");}

};

int main()
{
A a;
B b;
C c;
D d;
float f;

Test test;
test.f(a); // Will print "non-template"
test.f(b); // Will print "non-template"
test.f(c); // Will print "non-template"
test.f(d); // Will print "template"
test.f(f); // Will print "template"
}

编辑:

如果您使用的编译器不完全符合 C++11(因此不支持函数模板上的默认模板参数),您可能需要更改 f 的模板重载的定义()如下:

template<typename T>
typename enable_if<!is_base_of<A, T>::value, void>::type
f(T&) { cout << ("template\n"); }

程序的行为将是相同的。注意如果f()的返回类型是void,你可以省略enable_if类模板的第二个参数。

关于c++ - C++ 中的模板特化和派生类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14797303/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com