简体   繁体   中英

using static_assert in a class - how?

I'm trying to make it simple to check at compile time whether the conversion of one value to a new type preserves the value. There may be something in the STL that can do this for me, but I don't see it, so I wrote one. It works, but I wanted to convert it to a class in order to make the use a little simpler for others. I can't get that to work and I feel like I'm missing something obvious.

This works fine:

    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");

But the call is ungainly, so I wanted something more like

    CheckIt<unsigned int>(-7)

and so I attempted

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

I've tried various combinations of const and constexpr (and discovered parameters can't be constexprs, which is annoying). Everything I try results in g++ complaining that x is not a constant expression in the constructor.

What am I missing? checkv, and the constructor, are both always called with constants, like -7. checkv() is happy to evaluate at compile time and I can't see where using a constructor function to wrap that adds any additional burden to the compiler, but obviously it does. Note I need this to work in C++11, but I don't see where later versions will help. I have no problems checking at runtime, with assert, but I want the compile time solution for constants. TIA.

Passing a variable to a function will not work, as it is not a constant expression, thus the static_assert will not accept it.

You can try passing the value as a template parameter.

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>();
}

But it's not much cleaner.

edit: your can also use the "good" old macro's

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

int main() {
    CheckIt(unsigned int, -7);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM