SFINAE:它如何与派生类一起使用?

时间:2018-08-31 15:20:30

标签: c++ sfinae

我编写了以下代码:

template <typename Type>
class Int {
public:
    int value;
};

template <typename Type>
class Class : public Int<Type> {};

int var;

template <typename Type>
void foo(Type newValue) {
    var = newValue;
}

template <typename ClassType>
void foo(Int<ClassType>& newValue) {
    var = newValue.value;
}

int main() {
    Class<int> c;
    foo(c);
}

我遇到编译错误,因为编译器尝试调用foo的第一个实现(如果我尝试删除它,则代码可以正确编译)。由于SFINAE,编译器不是应该使用第二种实现吗?

1 个答案:

答案 0 :(得分:4)

这里没有使用SFINAE。选择第一个foo重载是因为它产生的匹配度要好于另一个重载(匹配是精确的,而不是另一个)。您可以尝试遍历here以获得有关SFINAE是什么的更多信息,我也建议您观看this awesome talk以了解如何正确进行操作(该讨论要先进一些)。
SFINAE的意思是,在推导模板中的类型时,您会想到格式错误的代码,只要匹配的内容就没有关系。在您的情况下,两个模板都匹配,因此适用常规解析规则。删除模板后,您的代码将归结为:

struct Base { int value; }
struct Derived : public Base {};
int var;
void foo(Derived val) { var = val; }
void foo(const Base& val) { var = val.value; }

int main()
{
   Derived bar;
   bar.value = 3;
   foo(bar); // will try to call first foo and compilation will fail
}