използване на 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() се радва да оцени по време на компилиране и не виждам къде се използва функция на конструктор за обвиване, което добавя допълнителна тежест към компилатора, но очевидно го прави. Забележете, че имам нужда от това, за да работи в C++11, но не виждам къде по-късните версии ще помогнат. Нямам проблеми с проверката по време на изпълнение, с assert, но искам решението по време на компилиране за константи. TIA.


person Scott M    schedule 04.11.2019    source източник
comment
x трябва да бъде параметър на шаблон.   -  person HolyBlackCat    schedule 04.11.2019
comment
Пропускате, че аргументът на функцията не е постоянен израз, дори ако самата функция е постоянен израз. Предполагам, че писането на static_assert(checkV<unsigned int>(-7), "No"); ще бъде единствената опция за c++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