4

有没有办法解决以下问题:

此代码生成 C4702 警告“无法访问的代码”(在 VC++ 15.8 上/std:c++17

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
}

为了抑制 C4100 '未引用的形式参数'警告,我已经在使用这个技巧

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

添加的简单想法

    else
    {
        return false;
    }

导致警告 C4715 '并非所有控制路径都返回一个值'。

4

2 回答 2

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;
}

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

于 2018-09-09T12:50:08.583 回答
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表达式的 bool 结果,编译器实际上产生了两个函数。此版本在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) ;

这将停止发出警告。

于 2018-09-10T12:38:26.487 回答