Forbid integer conversion with precision loss

后端 未结 3 743
庸人自扰
庸人自扰 2021-02-15 18:00

How to prevent such code from compiling?

#include 
#include 
#include 
#include 

int main() {
  std::         


        
3条回答
  •  傲寒
    傲寒 (楼主)
    2021-02-15 18:21

    You could start writing a wrapper for your integral types to match the exact type (or some conditions).

    #include 
    #include 
    #include 
    #include 
    #include 
    
    template  struct conjunction : std::true_type {};
    template  struct conjunction : B1 {};
    template 
    struct conjunction
        : std::conditional_t, B1> {};
    
    template  struct int_wrapper {
      explicit int_wrapper() : _val{T{}} {}
    
      explicit int_wrapper(const int_wrapper &other) : _val{other._val} {}
    
      template  explicit int_wrapper(U val) : _val{val} {
        static_assert(sizeof(T) >= sizeof(U), "Size mismatch.");
        static_assert(conjunction, std::is_signed>::value,
                      "sign mismatch");
      }
    
      explicit operator T() { return _val; }
      explicit operator T() const { return _val; }
    
      T _val;
    };
    
    std::ostream &operator<<(std::ostream &stream, const int_wrapper &v) {
      stream << v._val;
      return stream;
    }
    
    int main() {
      std::vector> v;
      v.emplace_back(std::numeric_limits::max());
      std::cout << v.back() << std::endl;
    
      return 0;
    }
    

    clang on macOS gives you error like:

    so.cpp:18:60: error: non-constant-expression cannot be narrowed from type 'unsigned long long' to 'short' in initializer list
          [-Wc++11-narrowing]
      template  explicit int_wrapper(U val) : _val{val} {
                                                               ^~~
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1752:31: note: in
          instantiation of function template specialization 'int_wrapper::int_wrapper' requested here
                ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
                                  ^
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1668:18: note: in
          instantiation of function template specialization 'std::__1::allocator >::construct,
          unsigned long long>' requested here
                {__a.construct(__p, _VSTD::forward<_Args>(__args)...);}
                     ^
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1514:14: note: in
          instantiation of function template specialization 'std::__1::allocator_traits >
          >::__construct, unsigned long long>' requested here
                {__construct(__has_construct(),
                 ^
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1643:25: note: in
          instantiation of function template specialization 'std::__1::allocator_traits >
          >::construct, unsigned long long>' requested here
            __alloc_traits::construct(this->__alloc(),
                            ^
    so.cpp:37:5: note: in instantiation of function template specialization 'std::__1::vector,
          std::__1::allocator > >::emplace_back' requested here
      v.emplace_back(std::numeric_limits::max());
        ^
    so.cpp:18:60: note: insert an explicit cast to silence this issue
      template  explicit int_wrapper(U val) : _val{val} {
                                                               ^~~
                                                               static_cast( )
    so.cpp:19:5: error: static_assert failed "Not the same size."
        static_assert(sizeof(T) >= sizeof(U), "Not the same size.");
        ^             ~~~~~~~~~~~~~~~~~~~~~~
    so.cpp:20:5: error: static_assert failed "sign mismatch"
        static_assert(conjunction, std::is_signed>::value,
        ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    3 errors generated.
    

提交回复
热议问题