Here is a minimal example:
struct incomplete_type;
template<typename T>
struct foo
{
using type = std::conditional_t<std::is_arithmetic_v<T>,
std::conditional_t<sizeof(T) < sizeof(void*), int, float>,
double>;
};
foo<incomplete_type> f;
will cause error because it will do sizeof with type, even though incomplete_type
is not a arithmetic type(iow, it will not go into sizeof branch logically). live demo
So, I want to defer sizeof
:
first attempt(fail)
template<typename T>
auto
foo_aux()
{
if(sizeof(T) < sizeof(T*))
return 0;
else
return 0.0f;
}
conditional_t<std::is_arithmetic_v<T>, decltype(foo_aux<T>()), double>
still trigger the same error.
second attempt(fail)
template<typename T, bool>
struct foo_aux_aux
{
using type = float;
};
template<typename T>
struct foo_aux_aux<T, true>
{
using type = int;
};
template<typename T, bool = false>
struct foo_aux : foo_aux_aux<T, sizeof(T) < sizeof(void*)>
{};
conditional_t<std::is_arithmetic_v<T>, typename foo_aux<T>::type, double>
still trigger the same error.
third attempt(success)
template<typename T, bool comp>
struct foo_aux_aux
{
using type = float;
};
template<typename T>
struct foo_aux_aux<T, true>
{
using type = int;
};
template<typename T, bool isArithmeticType>
struct foo_aux
{
using type = double;
};
template<typename T>
struct foo_aux<T, true>
{
using type = typename foo_aux_aux<T, sizeof(T) < sizeof(void*)>::type;
};
Yes, it works as expected, but its really tedious and ugly.
Do you have an elegant way here?