Я предлагаю что-то другое.
Вместо std::cout
(или нет) значений expected
и actual
вы можете вывести значение, возвращаемое функцией, вызванной из значений. Таким образом, вы можете различить (перегрузить) поведение вызываемой функции.
Я имею в виду ... предположим, вы пишете две версии функции maybePrint()
.
Первая - это сквозная функция шаблона, SFINAE включается только в том случае, если тип шаблона является печатаемым
template <typename T>
auto maybePrint (T const & t) -> decltype( std::cout << t, t )
{ return t; }
Второй, вызываемый, когда первый недоступен (поэтому, когда аргумент недоступен для печати), возвращает информативную строку (ну ... может быть, выбрать лучшую строку) [РЕДАКТИРОВАТЬ: изменено после отчета из Jarod42]
template <typename ... Ts>
std::string maybePrint (Ts const & ...)
{ return "[maybe not]"; }
Итак, ваш AreEqual()
станет
template <typename T>
static void AreEqual(const T& expected,
const T& actual,
const std::string& message = "")
{
if ( ! (actual == expected) )
std::cout << "Expected " << maybePrint(expected) << ", got "
<< maybePrint(actual) << ". " << message;
}
Я предлагаю это решение также потому, что завтра или в далеком будущем у вас может возникнуть соблазн изменить AreEqual()
для дифференциации типов шаблонов.
Это потому что следующий звонок
AreEqual(1, 2l, "abc\n");
выдает ошибку компиляции, поскольку компилятор не может выбирать между T = int
(1
- int
) и T = long
(2l
- long
).
Если вы переписываете AreEqual()
, получая два аргумента (потенциально) двух разных типов
template <typename T1, typename T2>
static void AreEqual (T1 const & expected,
T2 const & actual,
std::string const & message = "")
{
if ( ! (actual == expected) )
std::cout << "Expected " << maybePrint(expected) << ", got "
<< maybePrint(actual) << ". " << message;
}
предыдущий вызов компилируется, потому что T1
выводится int
и T2
выводится long
.
Если вы включаете одну или другую версию AreEqual()
в соответствии с T1
и T2
, у вас есть (потенциально) четыре случая (T1
и T2
для печати; T1
для печати, T2
нет; T2
для печати, T1
не для печати; T1
и T2
не для печати), поэтому четыре версии AreEqual()
.
Работая через maybePrint()
, вы поддерживаете один AreEqual()
.