Проблема вашего кода в том, что когда вы звоните max_sizeof<T>()
с одним T
типами, оба
template <class T>
static constexpr int maxSizeOf() {
return sizeof(T);
};
и
template <class T, class... Ts>
static constexpr int maxSizeOf() {
return static_max(sizeof(T), maxSizeOf<Ts...>());
};
совпадают.Таким образом, компилятор не может выбрать правильный.
Вы можете решить с помощью if constexpr ( sizeof...(Ts) )
, как предлагает dontpanic, но if constexpr
доступен только начиная с C ++ 17.
Возможное (и элегантное, IMHO) решение, работающее также в C ++ 11 и C ++ 14, заключается в удалении функции only-one-type и добавлении следующей функции нулевого типа
template <int = 0>
static constexpr std::size_t maxSizeOf()
{ return 0u; };
Thisспособ, когда вы вызываете maxSizeOf<Ts...>()
, когда sizeof...(Ts) > 0u
, вызывается версия одного или нескольких типов;когда sizeof...(Ts) == 0u
(то есть: когда список Ts...
равен empy), int = 0
(без типов) совпадает.
Другое предложение: sizeof()
- это значение std::size_t
, поэтому лучше, еслиmaxSizeOf()
return a std::size_t
Ниже приводится полностью рабочее (также C ++ 11) решение
#include <iostream>
template <typename T>
static constexpr T static_max (T a, T b)
{ return a < b ? b : a; }
template <typename T, typename ... Ts>
static constexpr T static_max (T a, Ts ... bs)
{ return static_max(a, static_max(bs...)); }
template <int = 0>
static constexpr std::size_t maxSizeOf()
{ return 0u; };
template <typename T, typename ... Ts>
static constexpr std::size_t maxSizeOf()
{ return static_max(sizeof(T), maxSizeOf<Ts...>()); };
template <typename ... Ts>
struct foo
{ static constexpr auto value = maxSizeOf<Ts...>(); };
int main ()
{
std::cout << foo<int, long, long long>::value << std::endl;
}
Но, как заметил Ашеплер (спасибо!), Это решениеработает, но не использует вариационную версию static_max()
.
Альтернативой, которая использует вариационную версию static_max()
, является перезапись вариационной версии maxSizeOf()
не рекурсивным способом, апросто распаковываем список переменных следующим образом
template <typename ... Ts>
static constexpr std::size_t maxSizeOf()
{ return static_max(sizeof(Ts)...); }
Теперь это базовый вариант (версия нулевого типа) maxSizeOf()
, который больше не используется и может быть удален.
В любом случаеКак предлагает NathanOliver, вы можете использовать std::max()
(версия, получающая список инициализаторов), которая, начиная с C ++ 14, равна constexpr
.
Итак, начиная с C ++ 14, выможно просто написать
#include <algorithm>
#include <iostream>
template <typename ... Ts>
struct foo
{ static constexpr auto value = std::max({sizeof(Ts)...}); };
int main ()
{
std::cout << foo<int, long, long long>::value << std::endl;
}