использование static_assert в классе - как?

Я пытаюсь упростить проверку во время компиляции, сохраняет ли значение преобразование одного значения в новый тип. В 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() с удовольствием оценивает во время компиляции, и я не вижу, где использование функции конструктора для переноса добавляет какую-либо дополнительную нагрузку на компилятор, но, очевидно, это так. Примечание. Мне нужно, чтобы это работало в С++ 11, но я не вижу, где помогут более поздние версии. У меня нет проблем с проверкой во время выполнения с помощью assert, но мне нужно решение для времени компиляции для констант. ТИА.


person Scott M    schedule 04.11.2019    source источник
comment
x должен быть параметром шаблона.   -  person HolyBlackCat    schedule 04.11.2019
comment
Вы упускаете из виду, что аргумент функции не является постоянным выражением, даже если сама функция является постоянным выражением. Я предполагаю, что запись static_assert(checkV<unsigned int>(-7), "No"); была бы единственным вариантом для С++ 11.   -  person user7860670    schedule 04.11.2019
comment
I want the compile time solution for constants — значит, вы хотите определить, является ли параметр константой, а затем использовать static_assert? Если он должен быть только постоянным, используйте шаблоны.   -  person KamilCuk    schedule 04.11.2019
comment
Это не решает вопрос, но в теле checkV все круглые скобки, кроме тех, что в двух приведениях, избыточны.   -  person Pete Becker    schedule 04.11.2019
comment
передача x в качестве параметра функции никогда не сработает, так как это переменная, а не константное выражение.   -  person JHBonarius    schedule 04.11.2019
comment
вы должны использовать assert для проверки во время выполнения.   -  person Thomas    schedule 04.11.2019
comment
Возможно, это всего лишь проблема XY... мы помогаем вам исправить ваше решение, которое может быть не очень хорошим решение... В чем собственно проблема?... /зачем/ вам это нужно?   -  person JHBonarius    schedule 04.11.2019


Ответы (1)


Передача переменной в функцию не сработает, так как это не константное выражение, поэтому 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>();
}

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

редактировать: вы также можете использовать «добрый» старый макрос

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

int main() {
    CheckIt(unsigned int, -7);
}
person JHBonarius    schedule 04.11.2019
comment
Я думаю, моя проблема в том, что вы не можете использовать constexpr для объявления параметра функции. Мне нужно, чтобы это работало, а затем SFINAE позволял этому варианту шаблона безвредно ошибаться, если компилятор видит, что значение не является константой. Я понимаю, почему комитет так и не поддержал это; это, вероятно, единственный случай, когда это было бы полезно. Ну что ж. - person Scott M; 28.12.2019