Упорядочение перегрузок функций имеет значение?

physicus спросил: 11 марта 2019 в 07:42 в: c++

Я столкнулся с ситуацией, когда порядок перегрузки функций имеет значение. Я думал, что причиной должна быть часть SFINAE с std::enable_if ((я дополнительно проверил код без std::enable_if, только с шаблонами, а затем выполняется код, независимо от порядка перегрузки функций.))

Я сделал из него минимальный рабочий пример.

Этот блок кода работает

#include <type_traits>template <bool C, typename R = void>
using EnableIf = typename std::enable_if<C, R>::type;template <typename T, typename R = void>
using IfIsArithmetic = EnableIf<std::is_arithmetic<T>::value, R>;template <typename S>
IfIsArithmetic<S, void> Add(S const &scalar1, S const &scalar2, S &ret)
{
 ret = scalar1 + scalar2;
}template <typename S>
IfIsArithmetic<S, S> Add(S const &scalar1, S const &scalar2)
{
 S ret;
 Add(scalar1, scalar2, ret);
 return ret;
}using T = float;int main(){
  T a = 3.1;
  T b = 3.5;
  T c{Add(a, b)};
}

, тогда как следующее не компилируется (реализации функций Add() меняются местами)

#include <type_traits>template <bool C, typename R = void>
using EnableIf = typename std::enable_if<C, R>::type;template <typename T, typename R = void>
using IfIsArithmetic = EnableIf<std::is_arithmetic<T>::value, R>;template <typename S>
IfIsArithmetic<S, S> Add(S const &scalar1, S const &scalar2)
{
 S ret;
 Add(scalar1, scalar2, ret);
 return ret;
}template <typename S>
IfIsArithmetic<S, void> Add(S const &scalar1, S const &scalar2, S &ret)
{
 ret = scalar1 + scalar2;
}using T = float;int main(){
  T a = 3.1;
  T b = 3.5;
  T c{Add(a, b)};
}

Компилятор дает следующая ошибка

test.cpp: In instantiation of ‘IfIsArithmetic<S, S> Add(const S&, const S&) [with S = float; IfIsArithmetic<S, S> = float]’:
test.cpp:28:15:   required from here
test.cpp:13:5: error: no matching function for call to ‘Add(const float&, const float&, float&)’
  Add(scalar1, scalar2, ret);
  ~~~^~~~~~~~~~~~~~~~~~~~~~~
test.cpp:10:22: note: candidate: template<class S> IfIsArithmetic<S, S> Add(const S&, const S&)
 IfIsArithmetic<S, S> Add(S const &scalar1, S const &scalar2)
                      ^~~
test.cpp:10:22: note:   template argument deduction/substitution failed:
test.cpp:13:5: note:   candidate expects 2 arguments, 3 provided
  Add(scalar1, scalar2, ret);
  ~~~^~~~~~~~~~~~~~~~~~~~~~~

Похоже, что компилятор пытается использовать первую перегрузку функции, даже если подпись не выравнивается.

Может быть, некоторые из Вы можете дать мне подсказку, с каким правилом поиска функции C ++ связана эта проблема!

0 ответов