Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 确定比较中文字的有效类型_C++_Templates_Macros_Compiler Warnings - Fatal编程技术网

C++ 确定比较中文字的有效类型

C++ 确定比较中文字的有效类型,c++,templates,macros,compiler-warnings,C++,Templates,Macros,Compiler Warnings,以下是我定义的宏的简化版本: #define CHECK_EQ(a, b) do { if ((a) != (b)) abort(); } while (false) 这是可行的,但现在我想对评估的a/b值做额外的工作,并且只想对每个值评估一次。换句话说,类似于: #define CHECK_EQ(a, b) \ do { \ const auto a_eval = (a); \ const auto

以下是我定义的宏的简化版本:

#define CHECK_EQ(a, b) do { if ((a) != (b)) abort(); } while (false)
这是可行的,但现在我想对评估的a/b值做额外的工作,并且只想对每个值评估一次。换句话说,类似于:

#define CHECK_EQ(a, b)          \
  do {                          \
    const auto a_eval = (a);    \
    const auto b_eval = (b);    \
    if (a_eval != b_eval) {     \
      /* Print a_eval/b_eval */ \
      abort();                  \
    }                           \
  } while (false)
但这会中断某些当前使用,触发
-Wsign compare
,例如
CHECK\u EQ(一些未签名,1)
。我想要的是,而不是
auto
,来确定比较的每一侧将被转换为用于比较的类型。假设示例:

#define CHECK_EQ(a, b)                                           \
  do {                                                           \
    using CmpType = CommonType<decltype(a), decltype(b)>::type;  \ What goes here??
    const CmpType a_eval = (a);                                  \
    const CmpType b_eval = (b);                                  \
    if (a_eval != b_eval) {                                      \
      /* Print a_eval & b_eval */                                \
      abort();                                                   \
    }                                                            \
  } while (false)
#定义检查等式(a,b)\
做{\
使用CmpType=CommonType::type;\这里是什么??
常数cmp类型a_eval=(a)\
常数cmptypeb_eval=(b)\
如果(a_eval!=b_eval){\
/*打印a_评估和b_评估*/\
中止()\
}                                                            \
}while(假)
我怀疑这也不太正确,因为decltype(1)将是int。有没有办法在不修改现有的
CHECK\u EQ
调用或抑制警告的情况下实现我想要的功能

编辑:
关于什么应该和不应该返回警告,似乎有点困惑。当其中一个参数为正文本时,使用
auto
会返回一个不必要的警告,这也是一个有效的无符号文本(但
auto
会导致
带符号的
)。换句话说,理想情况下,
CHECK_EQ(a,b)
会产生警告,当且仅当
a==b
会产生警告时。第二个最佳解决方案将允许混合类型,只要最终执行的比较是安全的,即类型的w.r.t.符号。这似乎是通过使用
std::common_type

实现的。是否可以使用模板函数进行比较

#include <iostream>

template<typename T1, typename T2>
static inline bool _NotEqual(const T1& a, const T2& b)
{
  if (static_cast<T2>(static_cast<T1>(b)) == b) {
    return a != static_cast<T1>(b);
  } else {
    return static_cast<T2>(a) != b;
  }
}

#define CHECK_EQ(a, b)                                          \
  do {                                                          \
    const auto a_eval = (a);                                    \
    const auto b_eval = (b);                                    \
    if (_NotEqual(a_eval, b_eval)) {                            \
      std::cerr << a_eval <<" != "<< b_eval << std::endl;       \
      abort();                                                  \
    }                                                           \
  } while (false)

int main()
{
  CHECK_EQ(1U, 1);
  CHECK_EQ(2, 2.2);
}
#包括
模板
静态内联bool_NotEqual(常数T1&a、常数T2&b)
{
if(静态_cast(静态_cast(b))==b){
返回a!=静态施法(b);
}否则{
返回静态_cast(a)!=b;
}
}
#定义检查等式(a、b)\
做{\
常数自动评估=(a)\
const auto b_eval=(b)\
如果(_NotEqual(a_eval,b_eval)){\
标准::cerr(编辑:最后有一个替代解决方案)

解决方案1(原件) 这永远不会正确工作,并且对于CommonType和
std:::common_type
都是不正确的。它过去和将来都是不正确的,因为
~(0U)!=-1
在这样的方案中计算为false(假设2的补码),您似乎期望它返回
true

我建议使用模板函数:

// check if this is a simple int literal 
// such as 1, 0, 6789, but not 1U and neither expressions like -1.
template <class T1, class T2>
bool is_same(const T1& a, const T2&b)
{
   if (std::is_signed_v<T1> && !std::is_signed_v<T2>) {
       // some compilers might warn about the following,
       // in that case make it an "if constexpr" instead.
       if (a < 0) return false;
   }
   if (!std::is_signed_v<T1> && std::is_signed_v<T2>) {
       if (b < 0) return false;
   }
   std::common_type_t<T1, T2> a_common = a;
   std::common_type_t<T1, T2> b_common = b;
   return a == b;
}
但是如果我们做到了,为什么不一直使用模板函数呢

template <typename T, typename U>
void check_eq(const T& a, const U& b)
{
   if (!is_same(a,b))
   {
       /* print a and b */
       abort();
   }
}
然后可以在比较函数中使用宏:

template <bool suppress_sign_warnings, class T1, class T2>
bool is_same(const T1 & a, const T2 & b)
{
    if constexpr (suppress_sign_warnings) {
        std::common_type_t<T1, T2> a_common = a, b_common = b;
        return a_common == b_common;
    } else {
        return a == b;
    }
}

#define CHECK_EQ(a, b)          \
  do {                          \
    const auto a_eval = (a);    \
    const auto b_eval = (b);    \
    constexpr bool any_literal = IS_INT_LITERAL(a) || IS_INT_LITERAL(b); \
    if (! is_same<any_literal>(a_eval, b_eval)) {     \
      /* Print a_eval/b_eval */ \
      abort();                  \
    }                           \
  } while (false)
但这产生了一个警告:

void foo(int a, unsigned b = 1u)
{
   CHECK_EQ(a, b); // like a == b
}

您是在寻找
std::common_type
?还是可能是
decltype(a+b)
?在这种情况下,警告对我来说是有效的(也就是说,它是关于调用代码的合法潜在问题的警告)。您应该使用适当的强制转换,以确保调用宏时,
a
b
表达式具有可比性,而不是在宏本身内。为什么要继续使用宏?随着宏越来越长,使用宏的适当性越来越小。我只是按照原始海报的示例,尝试进行最小的更改抱歉,~(0u)是从哪里来的?为什么你说我希望它与-1不同?另外,我不熟悉普通类型,我想这就是我所需要的;做is_签名检查而不是跳到普通类型部分的目的是什么?@Luis问题有
CHECK_EQ(一些未签名,1)
.0u是0的无符号值。因此
~(0u)
是最大无符号值。无符号值是正数,并且在数学上不同于所有负值,例如
-1
。编译器认为语言进行的比较在数学上是不正确的,这就是我试图在回答中避免的。答案试图维护数学正确性,就像其他语言会自动更新。@Luis我已经根据您的第一个备选方案更新了答案-以不同的方式处理int文本,并仅对literalsHanks@Michael禁止警告,我想做与literal
a==b
表达式完全相同的事情并不容易
template <bool suppress_sign_warnings, class T1, class T2>
bool is_same(const T1 & a, const T2 & b)
{
    if constexpr (suppress_sign_warnings) {
        std::common_type_t<T1, T2> a_common = a, b_common = b;
        return a_common == b_common;
    } else {
        return a == b;
    }
}

#define CHECK_EQ(a, b)          \
  do {                          \
    const auto a_eval = (a);    \
    const auto b_eval = (b);    \
    constexpr bool any_literal = IS_INT_LITERAL(a) || IS_INT_LITERAL(b); \
    if (! is_same<any_literal>(a_eval, b_eval)) {     \
      /* Print a_eval/b_eval */ \
      abort();                  \
    }                           \
  } while (false)
CHECK_EQ(1, 1u); // like 1 == 1u
void foo(int a, unsigned b = 1u)
{
   CHECK_EQ(a, b); // like a == b
}