использование static_assert в классе - как? - PullRequest
2 голосов
/ 04 ноября 2019

Я пытаюсь упростить проверку во время компиляции, сохраняет ли преобразование одного значения в новый тип значение. В STL может быть что-то, что может сделать это для меня, но я этого не вижу, поэтому я написал один. Это работает, но я хотел преобразовать его в класс, чтобы сделать использование немного проще для других. Я не могу заставить это работать, и я чувствую, что упускаю что-то очевидное.

Это прекрасно работает:

    template <typename T, typename Q>
    constexpr bool checkV(const Q x) 
    {return x == (T)x && ((x < 0) == ((T)x < 0));}

    static_assert(checkV<unsigned int>(-7), "No");

Но звонок неуклюжий, поэтому я хотел что-то более похожее

    CheckIt<unsigned int>(-7)

и поэтому я попытался

    template<typename T>
    class CheckIt {public:
      template<typename Q>
      constexpr CheckIt(const Q x) {static_assert(checkV<T>(x), "No");}
};

Я пробовал различные комбинации const и constexpr (и обнаруженные параметры не могут быть constexprs, что раздражает). Все, что я пробую, приводит к тому, что g ++ жалуется, что x не является константным выражением в конструкторе.

Что мне не хватает? checkv и конструктор всегда вызываются с константами, например -7. checkv () рада оценить во время компиляции, и я не вижу, где использовать функцию конструктора для переноса, что добавляет компилятору дополнительную нагрузку, но, очевидно, это так. Обратите внимание, мне нужно, чтобы это работало в C ++ 11, но я не вижу, где более поздние версии помогут. У меня нет проблем с проверкой во время выполнения, с assert, но я хочу решение времени компиляции для констант. ТИА.

1 Ответ

0 голосов
/ 04 ноября 2019

Передача переменной в функцию не будет работать, поскольку она не является константным выражением, поэтому static_assert не примет ее.

Вы можете попробовать передать значение в качестве параметра шаблона.

template <typename T, typename Q>
constexpr bool checkV(const Q x)
{
    return x == static_cast<T>(x) && ((x < 0) == (static_cast<T>(x) < 0));
}

template <typename T, typename Q, Q N>
void CheckIt() {
    static_assert(checkV<T, Q>(N));
}


int main() {
    constexpr auto val = -7;
    CheckIt<unsigned int, decltype(val), val>();
}

Но это не намного чище.

edit: вы также можете использовать "хороший" старый макрос

#define CheckIt(x,y) static_assert(checkV<x, decltype(y)>(y));

int main() {
    CheckIt(unsigned int, -7);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...