Сравнение времени компиляции параметра шаблона - PullRequest
5 голосов
/ 30 июня 2011

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

Это что-то вроде следующего:

enum Time { Day, Week, Month };

template<Time t, int length>
class Timer
{
}

Теперь я должен ограничить создание экземпляра Timer таким образом, чтобы -

Timer<Day,8>, Timer<Day,9> и т. Д. Должны работать, но length не может быть меньше 8 при использовании с Day.

Аналогично, length не может быть меньше 10 при использовании с Week и т. Д. *

Может кто-нибудь помочь мне с тем, как этого можно достичь во время компиляции?

Ответы [ 5 ]

7 голосов
/ 30 июня 2011

Все остальные ответы идут на метапрограммирование для обнаружения условия, с другой стороны, я бы упростил задачу:

template<Time t, int length>
class Timer
{
    static_assert( (t == Day && length > 7) 
                 ||(t == Week && length > 10)
                 ||(t == Month && length > 99), "Invalid parameters"
};

Компилятор вызовет утверждение, если условия не выполнены, иЭто довольно просто проверить с помощью сообщения об ошибке и / или глядя на строку.

Использование инструментов SFINAE для отключения версий типа также дает тот же результат: код не будет компилироваться, но за счетсделать сообщения об ошибках более сложными для чтения: что означает, что Timer<Day,5> не тип?безусловно, это так, это экземпляр Timer<Time,int>!

РЕДАКТИРОВАТЬ: Выше static_assert реализован в C ++ 0x, в компиляторах без C ++ 0x вы можете реализовать static_assertкак макрос:

#define static_assert( cond, name ) typedef char sassert_##name[ (cond)? 1 : -1 ];

Этот простой макрос принимает строковый литерал в качестве второго аргумента, а не одно слово.Использование может быть:

static_assert( sizeof(int)==4, InvalidIntegerSize ) )

И сообщения об ошибках потребуют небольшого разбора, поскольку компилятор будет жаловаться (если условие не выполняется), что размер sassert_InvalidIntegerSize отрицателен.

6 голосов
/ 30 июня 2011

Передать результат length >= 8 в качестве аргумента шаблона bool вспомогательному шаблону.Обеспечить специализацию только для true.Сказав это, это звучит как домашнее задание, поэтому я оставлю вам кодирование.

Приветствия & hth.

3 голосов
/ 30 июня 2011

Вы можете сделать это:

template<bool> 
struct rule;

template<> 
struct rule<true> {};

template<Time Tm, int Len>
struct constraint;

//Rule for Day     
template<int Len>
struct constraint<Day, Len> : rule<(Len>= 8)>
{};

template<Time Tm, int Len>
class Timer : constraint<Tm, Len>
{
   //your code
};

Тестовый код:

int main() {
        Timer<Day, 7> timer1; //error 
        Timer<Day, 8> timer2; //okay
        return 0;
}

Демоверсии онлайн:


Аналогично, вы можете добавить правила для Week и Month как:

//Rule for Week
template<int Len>
struct constraint<Week, Len> : rule<(Len>= 10)>
{};

//Rule for Month
template<int Len>
struct constraint<Month, Len> : rule<(Len>= 100)>
{};
2 голосов
/ 30 июня 2011

Идея такого рода проверки обычно заключается в том, чтобы передать работу выделенному вспомогательному классу, который вы специализируете для каждого типа параметров.

template <typename T, size_t V>
class Foo
{
  static_assert(helper<T,V>::value, "Wrong Parameters");
};

Существует два способа проверки:

// Require full specialization
template <typename T, size_t V> struct helper: std::false_type {};

template <>
struct helper<Bar,0>: std::true_type {};

template <>
struct helper<Bar,4>: std::true_type {};


// Property like
template <typename T, size_t V> struct helper: std::false_type {};

template <size_t V>
struct helper<Bar, V>: std::integral_constant<bool, V <= 8> {};

Конечно, они предполагают возможности C ++ 0x. В C ++ 03 вам придется самостоятельно создавать простые классы true_type, false_type и integral_constant.

0 голосов
/ 30 июня 2011
enum Time { Day, Week, Month };
template<Time T> struct Length;
template<> struct Length<Day> { static const int value = 8 ; };
template<> struct Length<Week> { static const int value = 9; };
template<> struct Length<Month> { static const int value = 10; };

template<bool b> struct Limit;
template<> struct Limit<true> { typedef bool yes; };

#define COMPILE_ASSERT(V) typedef typename Limit<(V)>::yes checked

template<Time t, int length>
class Timer
{
  COMPILE_ASSERT(length >= Length<t>::value);
};

См. Демоверсию здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...