вариативный шаблон, диапазон, C

#c #tuples #variadic-templates #stdarray #non-type-template-parameter

#c #кортежи #вариативные шаблоны #stdarray #не-тип-шаблон-параметр

Вопрос:

Подумайте, что у меня есть структура.

 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){
    } 
};
 

Таким образом, эта структура содержит диапазон для любого типа T, и если он не задан, диапазон становится числовыми пределами этого типа.
Примечание: Конечно, я проверяю T , чтобы быть fundamental типом, но этот вопрос не об этом.

Теперь в моем случае использования я хочу иметь такую структуру

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

Но когда я хочу «определить» это что-то с помощью этого
using Defined = Something<int,Range<int>(100,200),Range<int>(200,300)>
Я получаю ошибку во время компиляции, потому Range<T> что это параметр шаблона, не относящийся к типу, и я его не использую C 20 . Поэтому я пошел дальше и обновил свою структуру диапазона следующим образом.

 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;
};
 

И шаблон моей Something структуры становится таким typename<T,typename... Args> , так что теперь using Defined = Something<int,Range<int,100,200>,Range<int,200,300>> работает. Итак, на данный момент у меня есть 2 вопроса: как я могу статически утверждать, что каждый из аргументов равен a Range<T,T min, T max> . Второй вопрос касается его хранения. Послушайте, я знаю, что мне нужно хранить ...Args в кортеже, но если вы посмотрите на мою реализацию Range, могу ли я как-то обернуть их в std::array<Range<T>,sizeof(args)> ?

Комментарии:

1. У меня такое ощущение, что » не использовать C 20 » недостаточно. Какую версию вы используете? В C 17 вы, вероятно, могли бы свернуть std::is_same_v или что-то подобное.

2. Я использую C 17, причина, по которой я не использую C 20, заключается в том, что компиляторы clang на телефонах по-прежнему частично поддерживают C 20

3. Отлично, тогда ответ Jarod42 подойдет как перчатка.

4. Больше нет Range<T> . Это Range<T, t1, t2> . Таким образом, тип теперь отличается в зависимости от минимального и максимального. Это означает, что вы не можете хранить разные диапазоны в одном массиве.

5. Обратите внимание, что в вашей первой версии конструктор со всеми значениями по умолчанию является конструктором по умолчанию. (таким образом, у вас есть дважды).

Ответ №1:

Вы можете создать признак 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{};
 

а затем сложите выражение (C 17)

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

Комментарии:

1. Мне нравится эта идея, не могли бы вы также дать совет по моему второму вопросу, или мне создать для этого новый вопрос?

2. Поскольку типы различаются, вы не можете хранить их в массиве.

3. Я написал комментарий об этом в части вопроса, пожалуйста, прочтите это)