Ваша ошибка в объявлении переменной c версии IsOstreamOutputtable()
template <typename>
static auto IsOstreamOutputtable (...)
{ return std::false_type {}; }
Вы объявляете ее как template функцию с параметром шаблона, который не может быть выведен из Аргументы.
Итак, когда вы вызываете функцию из decltype()
static const auto value =
decltype(IsOstreamOutputtable(std::declval<std::ostream&>(), std::declval<U>()))::value;
, компилятор не может принимать во внимание вариант c variadi.
Решения.
(1) вы можете явно указать параметр шаблона, вызвав IsOstreamOutputtable()
// ..........................VVV explicit template parameter
decltype(IsOstreamOutputtable<U>(std::declval<std::ostream&>(), std::declval<U>()))::value;
, чтобы компилятор мог использовать версию c variadi,
Проблема: это решение не работает для std::vector
версии
(2) (лучше), вы можете сделать версию IsOstreamOutputtable()
variadi c не шаблонной
// no needs of template
static auto IsOstreamOutputtable (...)
{ return std::false_type {}; }
Off Topi c: методы IsOstreamOutputtable()
вызываются только внутри decltype()
, поэтому нет необходимости определять, вам нужно только объявить их. (и если вы определяете их, пожалуйста, будьте последовательны: тело не может быть пустым для метода, возвращающего std::true_type
).
Используя также конечный тип возврата и другие незначительные упрощения, ваша машинопись может быть немного уменьшено
template <typename U>
struct OstreamOutputableTrait
{
template <typename T>
static auto IsOstreamOutputtable (T const & var)
-> decltype( std::declval<std::ostream&>() << var, std::true_type{} );
// special case for vector<T>
template <typename T>
static std::false_type IsOstreamOutputtable (std::vector<T> const &);
static std::false_type IsOstreamOutputtable (...);
static constexpr auto value
= decltype(IsOstreamOutputtable(std::declval<U>()))::value;
};