如果constexpr和C4702(以及C4100和C4715)

时间:2018-09-09 12:41:49

标签: c++ visual-c++ c++17 if-constexpr

是否可以解决以下问题:

此代码会生成C4702警告“无法访问的代码”(在VC ++ 15.8上,带有class invoice(models.Model): customer = models.CharField(max_length=256, blank=False) date = models.DateField(default=now) invoice_number = models.IntegerField(editable=False,default=1) total_quantity = models.DecimalField(max_digits=10, decimal_places=2) total_amount = models.DecimalField(max_digits=10, decimal_places=2) total_tax = models.DecimalField(max_digits=10, decimal_places=2) def save(self): if self._state.adding: last_invoice=invoice.objects.all().aggregate(largest=models.Max('invoice_number'))['largest'] if last_invoice is not None: self.invoice_number=last_invoice+1 super(invoice,self).save()

/std:c++17

为了消除C4100“未引用的形式参数”警告,我已经在使用技巧了

template <typename T, typename VariantType>
inline bool MatchMonostate( VariantType& variant )
{
    SUPPRESS_C4100( variant );
    if constexpr ( std::is_same_v<T, std::monostate> )
    {
        variant = std::monostate();
        return true;
    }
    return false;  // !!! unreachable if the above is true !!! => C4702
}

添加的简单想法

#define SUPPRESS_C4100(x) ((void)x)

产生警告C4715,“并非所有控制路径都返回值”。

2 个答案:

答案 0 :(得分:6)

这是无法实现的,因为对于基于模板参数的给定模板扩展,该函数将仅 通过条件并返回true,否则返回,否则失败并返回false。对于相同类型,绝对不可能出现任何一种情况。它实际上正在扩展到

if (true) {
  return true;
}
return false; // Obviously will never happen

我将其重写为只有一个return语句。

template <typename T, typename VariantType>
inline bool MatchMonostate( VariantType& variant )
{
    SUPPRESS_C4100( variant );
    bool retval = false;
    if constexpr ( std::is_same_v<T, std::monostate> )
    {
        variant = std::monostate();
        retval = true;
    }
    return retval;
}

此外,在条件为true的情况下, not 未使用。您可能希望将抑制警告(基本上变成(void)变量)的行移到else语句。

答案 1 :(得分:1)

作为直接问题的直接答案。关于if constexpr的主题。考虑一下:

template <typename T, typename ... params >
 inline bool match_monostate
  (std::variant<params ...> & variant) noexcept    
{
 if constexpr (std::is_same_v<T, std::monostate>)
 {
     variant = std::monostate{} ;
 //  compiles only if called with variant
 //  whose one alternative is std::monostate
     return true;
 }
 else {
    return false;
 }
}

根据if constexpr表达式的布尔结果,编译器实际上产生两个函数。当if constexpr()产生true时,产生此版本:

  template <typename T, typename ... params >
 inline bool 
 match_monostate  (std::variant<params ...> & variant)  noexcept
{
    variant = std::monostate{} ;
//  compiles only if called with variant
//  whose one alternative is std::monostate
    return true;
}

if constexpr()产生false时产生此版本:

template <typename T, typename ... params >
 inline bool 
 match_monostate  (std::variant<params ...> & variant)  noexcept
{
    return false;
}

第二个版本可能会发出有关未使用参数的警告。但是(似乎)如果使用最新版本的clang / gcc / msvc,则不会。对于较旧的编译器,如“ old123987”也指出可以将标准属性添加到签名中。像这样:

 template <typename T, typename ... params >
 inline bool 
 match_monostate  ([[maybe_unused]] std::variant<params ...> & variant) ;

这将停止发出警告。