2014-12-12 2 views
6

Я не могу найти средство проверки времени компиляции, поэтому я пробовал некоторые подходы к разработке собственного, где вы должны ввести значение, о котором идет речь, значение min и максимальное значение, чтобы контролер return true, если значение находится между двумя конечными точками.Проверка времени отклика времени компиляции

Мой первый подход был просто чтобы быть в состоянии сравнить Интс и это выглядело так:

template<int Val, int LoEnd, int HiEnd> 
struct is_in_interval : public std::integral_constant<bool, Val >= LoEnd && Val <= HiEnd>::type 
{}; 

Вызов функции будет выглядеть

bool inside = is_in_interval<3, 1, 10>::value; 

и что, казалось, работали. Я мог бы даже сделать это сбой во время компиляции, если нижний конец был выше, чем выше конца:

template<int val, int LoEnd, int HiEnd> 
struct is_in_interval : public std::integral_constant< typename std::enable_if<LoEnd <= HiEnd, bool>::type, val >= LoEnd && val <= HiEnd>::type 
{}; 

Чтобы иметь возможность сравнивать любое значение, я пришел с этим:

template<typename T> 
struct is_in 
{ 
    template<T val, T LoEnd, T HiEnd> 
    struct closed_interval : public std::integral_constant< typename std::enable_if<LoEnd <= HiEnd, bool>::type, val >= LoEnd && val <= HiEnd>::type 
    {}; 
}; 

Теперь, однако, звонки стали более неясными:

bool inside = is_in<int>::closed_interval<3,1,10>::value; 

, но я все еще имел возможность использовать enable_if и даже может добавить больше (для проверки is_integral, например).

Вопрос в том, можно ли как-то сделать эту обобщенную версию более удобной для вызова, возможно, выведя тип (int) из не-типа (3,1,10) выше?

На заметка на поля я мог бы использовать:

template<typename T> 
constexpr bool isInInterval3(T val, T LoEnd, T HiEnd) 
{ 
    return val >= LoEnd && val <= HiEnd; 
} 

, но в этой функции я не думаю, что я могу использовать std::enable_if тип признак, чтобы утверждать, что LoEnd <= HiEnd.

+0

Вы все еще можете использовать 'isInInterval3' сделать проверку во время компиляции:' constexpr BOOL assert_isIn (T Const вал, Т сопз мин, T Const макс) {вернуться значение> = min && val <= max? true: выбросить «вне диапазона»; } 'При использовании такой функции в контексте, где требуется постоянное выражение, вместо исключения вы получите ошибку времени компиляции. Но это не очень полезно; Я бы предпочел использовать 'static_assert (isInInterval3 (val, lo, hi)," !! ");' с вашим текущим определением. – dyp

+0

@ dyp Ни SFINAE-дружественный, ни красивый и элегантный способ закончить его? – Columbo

+0

@Columbo Как основной строительный блок, я думаю, что '' isInterval3'' полезен. Вы можете построить как SFINAE, так и жесткую ошибку. Как я уже сказал, я думаю, что мой 'assert_isIn' не очень полезен. – dyp

ответ

0

Вы можете указать как «TYPENAME T» и другие параметры в одном шаблоне:

template<typename T, T val, T LoEnd, T HiEnd> 
struct is_in_interval : public std::integral_constant< 
typename std::enable_if<LoEnd <= HiEnd, bool>::type, val >= LoEnd && val <= HiEnd>::type 
{}; 

Затем вы можете определить макрос in_interval только с параметрами Валя, LoEnd и HiEnd, который будет вызывать is_in_interval с первым параметром шаблона , например, decltype(val):

#define in_interval(val, LoEnd, HiEnd) (is_in_interval<decltype(val), val, LoEnd, HiEnd>::value) 

И вы можете использовать его следующим образом:

cout << in_interval(3, 1, 10) << endl; 

Это все работает на моем VS2012