if constexpr 和 C4702(以及 C4100 和 C4715)
if constexpr and C4702 (and C4100, and C4715)
有没有办法解决以下问题:
此代码产生 C4702 警告 'unreachable code'(在 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 'unreferenced formal parameter'警告,我已经在使用技巧了
#define SUPPRESS_C4100(x) ((void)x)
添加的简单思路
else
{
return false;
}
导致警告 C4715 'not all control paths return a value'。
它是不可访问的,因为对于基于模板参数的模板的给定扩展,该函数将仅通过条件并且return真或 失败并且 return 错误。对于同一类型,不可能有任何一种情况。它基本上扩展到
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;
}
此外,在条件为真的情况下,变体 not 未使用。您可能希望将抑制警告(基本上变成 (void)variant)的那行移动到 else 语句。
作为对直接问题的直接回答。关于 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()
产生错误时生成的:
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) ;
这将停止发出警告。
有没有办法解决以下问题:
此代码产生 C4702 警告 'unreachable code'(在 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 'unreferenced formal parameter'警告,我已经在使用技巧了
#define SUPPRESS_C4100(x) ((void)x)
添加的简单思路
else
{
return false;
}
导致警告 C4715 'not all control paths return a value'。
它是不可访问的,因为对于基于模板参数的模板的给定扩展,该函数将仅通过条件并且return真或 失败并且 return 错误。对于同一类型,不可能有任何一种情况。它基本上扩展到
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;
}
此外,在条件为真的情况下,变体 not 未使用。您可能希望将抑制警告(基本上变成 (void)variant)的那行移动到 else 语句。
作为对直接问题的直接回答。关于 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()
产生错误时生成的:
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) ;
这将停止发出警告。