SFINAE:它如何与派生 class 一起工作?

SFINAE: How it works with derived class?

我写了下面的代码:

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,编译器不应该使用第二种实现吗?

这里没有使用SFINAE。选择第一个 foo 重载是因为它产生比另一个更好的匹配(匹配是精确的,与另一个相反)。你可以尝试通过here for more information on what SFINAE is, I'd also recommend watching 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
}