СФИНАЭ: Как это работает с производным классом? - PullRequest
0 голосов
/ 31 августа 2018

Я написал следующий код:

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 голосов
/ 31 августа 2018

Здесь нет SFINAE. Первая перегрузка foo выбрана потому, что она дает лучшее совпадение, чем другое (совпадение является точным, в отличие от другого). Вы можете попробовать здесь для получения дополнительной информации о том, что такое SFINAE, я бы также рекомендовал посмотреть этот потрясающий доклад , чтобы узнать, как это сделать правильно (доклад немного более продвинутый ).
Что означает 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
}
...