variadic template, Range, C++

321 views Asked by At

Consider I have a struct.

template<typename T>
struct Range{
    T min, max;
    
    Range() = default;
    Range(T min = std::numeric_limits<T>::min(),T max = std::numeric_limits::max()) :
                                   min(min), max(max){
    } 
};

So this struct holds a range for any type T, and if not given it the range becomes the numeric limits of that type. Note: Of course I check for T to be fundamental type but this question is not about that.

Now in my use case I want to have a struct like this

template<typename T,Range<T>...ranges>
struct Something{
    static std::array<Range<T>,sizeof...(ranges)> RANGES = {ranges...};
};

But when I want to "define" that something with this using Defined = Something<int,Range<int>(100,200),Range<int>(200,300)> I get compile-time error, because Range<T> is non-type template parameter and I am not using C++ 20. So I went further and updated my range struct like this.

template<typename T, T MIN = std::numeric_limits<T>::min(), T MAX = std::numeric_limits<T>::max()>
struct Range {
    T min = MIN, max = MAX;

    Range(T min, T max) : min(min), max(max) {}

    Range() = default;
};

And my Something struct's template becomes this typename<T,typename... Args> so now using Defined = Something<int,Range<int,100,200>,Range<int,200,300>> works. So at this point I've got 2 questions, how can I statically assert for each of args to be a Range<T,T min, T max> . The second questions is about storing that. Look, I know that I have to store ...Args in a tuple, but if you look at my implementation of Range, can I somehow wrap them in an std::array<Range<T>,sizeof(args)>?

1

There are 1 answers

3
Jarod42 On BEST ANSWER

You can create trait is_range:

template <typename> struct is_range : std::false_type{};

template<typename T, T MIN, T MAX>
struct is_range<Range<T, MIN, MAX> : std::true_type{};

and then fold expression (C++17)

template <typename ...Ts>
struct Something{
    static_assert((is_range<Ts>::value && ...));
    static std::tuple<Ts...> RANGES;
};