Это не ошибка при разрешении перегрузки. Другими словами, это откладывает выдачу вам ошибки, пока он не будет уверен, что вызов определенно не будет работать. После этого это ошибка.
struct example
{
template <typename T>
static void pass_test(typename T::inner_type); // A
template <typename T>
static void pass_test(T); // B
template <typename T>
static void fail_test(typename T::inner_type); // C
};
int main()
{
// enumerates all the possible functions to call: A and B
// tries A, fails with error; error withheld to try others
// tries B, works without error; previous error ignored
example::pass_test(5);
// enumerates all the possible functions to call: C
// tries C, fails with error; error withheld to try others
// no other functions to try, call failed: emit error
example::fail_test(5);
}
Следует также отметить, что разрешение перегрузки (и, следовательно, SFINAE) смотрит только на сигнатуру функции, , а не на определение . Так что это всегда будет неудачей:
struct example_two
{
template <typename T>
static int fail_test(T x)
{
return static_cast<int>(x);
}
template <typename T>
static int fail_test(T x)
{
return boost::lexical_cast<int>(x);
}
};
int main()
{
example_two::fail_test("string");
}
Нет ошибок ни для замены шаблона, ни для сигнатур функций, поэтому обе функции можно вызывать, даже если мы знаем, что первая не удастся, а вторая - нет. Так что это дает вам неоднозначную ошибку вызова функции.
Вы можете явно включить или отключить функции с помощью boost::enable_if
(или std::enable_if
в C ++ 0x, что эквивалентно boost::enable_if_c
). Например, вы можете исправить предыдущий пример с помощью:
struct example_two_fixed
{
template <typename T>
static boost::enable_if<boost::is_convertible<T, int>, int>
pass_test(T x) // AA
{
return static_cast<int>(x);
}
template <typename T>
static boost::disable_if<boost::is_convertible<T, int>, int>
pass_test(T x) // BB
{
return boost::lexical_cast<float>(x);
}
};
struct empty {} no_conversion;
int main()
{
// okay, BB fails with SFINAE error because of disable_if, does AA
example_two::pass_test(5);
// okay, AA fails with SFINAE error because of enable_if, does BB
example_two::pass_test("string");
// error, AA fails with SFINAE, does BB, fails because cannot lexical_cast
example_two::pass_test(no_conversion);
}