Funkcja nie może zwrócić typu. Powinieneś użyć szablonu.
Do wyboru między dwoma typami wystarczy built-in std::conditional
.
#include <type_traits>
#include <cstdint>
template <size_t n>
using type_from_size = typename std::conditional<(n < 256), uint8_t, uint16_t>::type;
//^if `n < 256`, the ::type member will be typedef'ed to `uint8_t`.
// otherwise, it will alias to `uint16_t`.
// we then give a convenient name to it with `using`.
template <size_t n>
struct X {
type_from_size<n> t;
//^use the template
};
Jeśli chcesz obsługiwać więcej niż dwie wartości, można zmienić wiele conditional
razem jak łańcuch if/else if/else
, ale OH MY EYES
template <size_t n>
using type_from_size =
typename std::conditional<(n <= 0xff), uint8_t,
typename std::conditional<(n <= 0xffff), uint16_t,
typename std::conditional<(n <= 0xffffffff), uint32_t,
uint64_t
>::type
>::type
>::type;
Można również użyć specjalizacji razem z std::enable_if
(SFINAE), aby był bardziej "niskiego poziomu":
template <size_t n, typename = void>
struct type_from_size_impl;
// Declare a "size_t -> type" function.
// - the `size_t n` is the input
// - the `typename = void` is a placeholder
// allowing us to insert the `std::enable_if` condition.
template <size_t n>
struct type_from_size_impl<n, typename std::enable_if<(n <= 0xff)>::type> {
using type = uint8_t;
};
// We add a partial specialization
// - in `std::enable_if<c>::type`, if `c` is true, `::type` will be typedef'ed to `void`
// - otherwise, `::type` will not be defined.
// - if `::type` is not defined, substitution failed,
// meaning we will not select this specialization
template <size_t n>
struct type_from_size_impl<n, typename std::enable_if<(n > 0xff && n <= 0xffff)>::type> {
using type = uint16_t;
};
template <size_t n>
struct type_from_size_impl<n, typename std::enable_if<(n > 0xffff && n <= 0xffffffff)>::type> {
using type = uint32_t;
};
template <size_t n>
struct type_from_size_impl<n, typename std::enable_if<(n > 0xffffffff)>::type> {
using type = uint64_t;
};
template <size_t n>
using type_from_size = typename type_from_size_impl<n>::type;
// Here we want to find a specialization of `type_from_size_impl<n>`
// All 4 specializations will be tried.
// If only one specialization works, we will use that one
// (Which is why we need to ensure the ranges are not overlapping
// otherwise the compiler will complain)
// Then we take the `::type` out the complete this "type-level function".
Myślę, że nie można zwrócić typu. Jednak możesz "zwrócić typ" z klasami szablonów poprzez 'typedef's. – PcAF
Boost.Hana powinien mieć coś do tego, ale to, czy wynik jest bardziej użyteczny, zależy od tego, co z nim zrobisz. W takim przypadku regularny szablon jest prawdopodobnie bardziej przydatny. – chris