C++ 比较C+中的两个整数是否相等+;具有未知的int类型

C++ 比较C+中的两个整数是否相等+;具有未知的int类型,c++,C++,基本上我想要的是一个简单的函数: template<typename A, typename B> is_the_same_value(A a, B b) { // return true if A is the same value as B } 将返回真值。clang/gcc对此发出警告:比较不同符号的整数 使用类似于a==b&((a>0)==(b>0))的方法可以工作,但仍然会触发编译器警告 您可以使用std::common_type删除警告 #include <

基本上我想要的是一个简单的函数:

template<typename A, typename B>
is_the_same_value(A a, B b)
{
    // return true if A is the same value as B
}
将返回真值。clang/gcc对此发出警告:
比较不同符号的整数


使用类似于
a==b&((a>0)==(b>0))
的方法可以工作,但仍然会触发编译器警告

您可以使用
std::common_type
删除警告

#include <type_traits>
template<typename A, typename B>
bool is_numbers_equal(A a, B b) {
    using C = typename std::common_type<A, B>::type;
    return (a > 0) == (b > 0) && static_cast<C>(a) == static_cast<C>(b);
    // or maybe `... && C(a) == C(b);`
}
#包括
模板
布尔数等于(A,B){
使用C=typename std::common_type::type;
返回(a>0)=(b>0)和静态(a)=静态(b);
//或者`……&&C(a)==C(b)`
}
好吧,这看起来很有趣,可以针对“相同”的类型对编译器进行优化:

#包括
模板
typename std::启用\u如果<
std::is_integral::value&&
std::is_integral::value&&
(std::is_signed::value^std::is_signed::value)
,bool>::类型
数字是否相等(A,B){
使用C=typename std::common_type::type;
返回(a>=0)=(b>=0)和
静态广播(a)=静态广播(b);
}
模板
typename std::启用\u如果<
! (
std::is_integral::value&&
std::is_integral::value&&
(std::is_signed::value^std::is_signed::value)
)
,bool>::类型
数字是否相等(A,B){
返回a==b;
}

对于不允许隐式转换(有符号/无符号等)的基于值的比较,可以选择检查类型是否相等:

#include <type_traits>

template<typename A, typename B>
bool is_the_same_value(const A&  a, const B& b)
{
    if constexpr(!std::is_same_v<A,B>) return false;
    else return a == b;
}
#包括
模板
布尔值是相同的值(常数A和A,常数B和B)
{
如果constexpr(!std::is_same_v)返回false;
否则返回a==b;
}

您不能使用
std::is_integral
检查这两种类型是否为int吗?然后将它们转换为有符号的
long
,然后比较它们。

您可以比较内存:

template<typename A, typename B>
bool is_the_same_value(A a, B b)
{
    return std::memcmp(&a,&b,sizeof(A)) == 0;
    // return true if A is the same value as B
}
模板
布尔是相同的值(A,B)
{
返回std::memcmp(&a,&b,sizeof(a))==0;
//如果A与B的值相同,则返回true
}

这对我来说并不是一个难题。有足够多的复杂因素,所以我不认为结果是“简单的”,但它远不是复杂的。只需一次处理一个已识别的问题,并确保这两个参数是对称的

问题1:将负值转换为无符号类型是错误的。
问题2:比较不同类型可能会导致编译器警告

template<typename A, typename B>
bool is_the_same_value(A a, B b)
{
    // Address issue 1 by returning false if exactly one of the parameters
    // is negative.
    if ( a < 0 && b >= 0 )
        return false;
    if ( b < 0 && a >= 0 )
        return false;
    // At this point, either both a and b are negative (hence A and B are signed types)
    // or both are non-negative (hence converting to an unsigned type is fine).

    // Address issue 2 by explicitly casting. Make sure you cast both
    // ways to keep things symmetric.
    return a == static_cast<A>(b)  &&
           b == static_cast<B>(a);
}
模板
布尔是相同的值(A,B)
{
//如果正好是其中一个参数,则返回false,以解决问题1
//答案是否定的。
如果(a<0&&b>=0)
返回false;
如果(b<0&&a>=0)
返回false;
//此时,a和b都是负数(因此a和b是有符号类型)
//或者两者都是非负的(因此可以转换为无符号类型)。
//通过显式强制转换来解决问题2。确保您同时强制转换了这两种类型
//保持事物对称的方法。
返回a==static_cast(b)&&
b==静态(a);
}

当然,有一些聪明的方法可以使代码更紧凑(并且可读性更低),但是编译器不应该能够为您进行这些优化吗?

对于我(在我的特定体系结构上),
-1
0xffffff
是相同的值,它们完全相同,具有相同的位。请定义两个变量“具有相同值”的含义。也许你只想
返回std::is_signed(a)^std::is_signed(b)| a==b(或类似的东西)?@KamilCuk仅当
int
在2的补码环境中有32位时,我猜@KamilCuk仍将不可原谅地触发a==b部分的编译器警告。并且std::is_signed接受一个类a参数,所以这里的a和B,所以int a=32;使用b=32;将返回false
是否相同\u将
-1
0xFFFFFFFF
进行比较时,值将不准确。它们可能具有相同的位模式,但不具有值。否。请不要这样做。这是Dailywtf.com上经常出现的事情之一。尝试编写自己的通用相等运算符,而不是在casting中适当地使用
=
,这要么会重新发明轮子(通过使用轮子)或者只是一个奇怪的东西,通过一个代码库扩散开来,团队中没有人能够向下一批新员工解释。我不认为他们在寻找相同的位模式。据我所知,他们想要的是数学等式。你的两个函数都不这样做。也就是说,我只是猜测,因为问题没有深入解释它们想要什么。是的,我想知道这两个值是否相同,我重命名了函数is_same_value来实现这一点。对于中给出的示例
-1,0xffffffff
,您的第一个函数失败question@eerorika我刚刚对原始帖子发表了评论。@plaisthos没有,当
int
为32位时,情况并非如此:@plaisthos我删除了以前的建议,转而支持我目前如何解释您的问题。
uintmax\t
intmax\t
的明显问题浮现在脑海中。从无符号到有符号的转换可能会有问题,但是你需要一个高于2^63的数字,这个数字高得离谱,可能足以满足99.9%以上遇到此线程的所有人。我的意思是,你面临与OP相同的转换警告-或者描述你如何解决该部分。@JMRC说“可能足以满足99.9%以上的人”这是一个很好的方法,可以保证你会撞到其他0.1%;)请注意,<代码> A>=0 < /C>将被优化,而<>代码> A> 0 < /C>不会。第二个解决方案看起来像典型的C++模板疯狂,我们现在都习惯了,并将其正确地保护:但是,如果它们具有相同的值,则不表示。1和255不是相同的值,即使存在两种不同类型和一种用途的平台
template<typename A, typename B>
bool is_the_same_value(A a, B b)
{
    return std::memcmp(&a,&b,sizeof(A)) == 0;
    // return true if A is the same value as B
}
template<typename A, typename B>
bool is_the_same_value(A a, B b)
{
    // Address issue 1 by returning false if exactly one of the parameters
    // is negative.
    if ( a < 0 && b >= 0 )
        return false;
    if ( b < 0 && a >= 0 )
        return false;
    // At this point, either both a and b are negative (hence A and B are signed types)
    // or both are non-negative (hence converting to an unsigned type is fine).

    // Address issue 2 by explicitly casting. Make sure you cast both
    // ways to keep things symmetric.
    return a == static_cast<A>(b)  &&
           b == static_cast<B>(a);
}