Use sizeof with incomplete type inside std::conditional

  • A+
Category:Languages

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 something 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?

 


In C++17, you can use if constexpr to do type computation. Just wrap the type into a dummy container and use value computation, then retrieve the type via decltype.

struct foo could be implemented like:

template<class T> struct type_ {     using type = T; };  template<class T> struct foo {     auto constexpr static type_impl() {         if constexpr (std::is_arithmetic<T>{}) {             if constexpr (sizeof(T) < sizeof(void*)) {                 return type_<int>{};             } else {                 return type_<float>{};             }         } else {             return type_<double>{};         }     }      using type = typename decltype(type_impl())::type; };  static_assert(std::is_same<foo<incomplete_type>::type, double>{}); 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: