有没有办法说服一个好的C++编译器警告关于从用户定义字面量构造用户定义类型中的溢出,如下所示的示例代码?至少(通过Godbolt)GCC和Clang警告相等内部代码中的溢出,但MSVC不会。没有人关心用户定义代码中的同样错误。
#include <iostream>
struct MyShort
{
short data;
constexpr MyShort ( short arg ) : data ( arg ) {}
};
constexpr MyShort operator "" _MyShort ( unsigned long long arg )
{
return MyShort ( arg );
}
struct UseMyShort
{
MyShort constexpr static var1 = 100000_MyShort;
short constexpr static var2 = 100000;
};
int main ( int argc, char** argv )
{
std::cout << UseMyShort::var1.data;
std::cout << UseMyShort::var2;
}
更新:感谢pyj和cigien的提示。当代码在编译时运行时,编译器不关心未执行的分支,因此非constexpr表达式是可以接受的。如果编译器执行了该路径,则会出现错误,这是期望的结果。我已经根据你们的解决方案进行了适应性修改,以便在调试模式下也能检测到运行时错误。下面是更新后的代码。我接受了cigien的答案,因为他们似乎承担了一个有缺陷的草稿的惩罚,而不是有缺陷的想法。
#include <iostream>
#include <limits>
#include <assert.h>
template <class elem>
constexpr elem rangeCheck ( unsigned long long arg )
{
if ( arg > std::numeric_limits<elem>::max() ) {
assert ( false );
}
return elem(arg);
}
struct MyShort
{
short data;
constexpr MyShort ( short arg ) : data ( arg ) {}
};
constexpr MyShort operator "" _MyShort ( unsigned long long arg )
{
return MyShort { rangeCheck<short> (arg) };
}
struct UseMyShort
{
// compile time error (GCC):-
// ... call to non-constexpr function ‘void __assert_fail(const char*, const char*, unsigned int, const char*)’
// assert ( false );
// ^
MyShort constexpr static var1 = 100000_MyShort;
short constexpr static var2 = 100000; // compile time warning (with GCC -Woverflow)
};
int main ( int, char** )
{
std::cout << UseMyShort::var1.data;
std::cout << UseMyShort::var2;
MyShort const var4 = 100000_MyShort; // runtime error
MyShort var5 = 100000_MyShort; // runtime error
return 0;
}