if constexpr and C4702 (and C4100, and C4715)
if constexpr and C4702 (and C4100, and C4715)
Is there a way to fix the following problem:
This code produces a C4702 warning 'unreachable code' (on VC++ 15.8 with /std:c++17
)
/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
to suppress the C4100 'unreferenced formal parameter' warning, I'm already using the trick
#define SUPPRESS_C4100(x) ((void)x)
The simple idea of adding
else
return false;
results in warning C4715 'not all control paths return a value' instead.
SUPRESS_C4100
Thx for pointing this out. Just using
bool MatchMonostate( [[maybe_unused]] VariantType& variant )
gets rid of C4100.– old123987
Sep 10 '18 at 12:02
bool MatchMonostate( [[maybe_unused]] VariantType& variant )
yes that works too. Although latest releases of the "big three" do no need even that ...
– user10133158
Sep 10 '18 at 12:22
Not sure which is your 3rd. My VC++ 15.8.3 with /std:c++latest will issue C4100 without
[[maybe_unused]]
– old123987
Sep 10 '18 at 15:34
[[maybe_unused]]
... I might be missing something .. please go to your devl command prompt and do "
cl /Bv
" .That gives the version nums. mine is 19.15.26726.0 ... I shall re-try in an empty project ...– user10133158
Sep 11 '18 at 18:24
cl /Bv
2 Answers
2
It's unreachable because for a given expansion of the template based on the template arguments the function will only ever pass the condition and return true or fail and return false. There is no case where it could go either way for the same type. It's essentially expanding to
if (true)
return true;
return false; // Obviously will never happen
I'd rewrite it to only have a single return statement.
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;
Also, in the case where the condition is true variant is not unused. You may want to move that line that suppresses the warning (which basically turns into (void)variant) to an else statement.
Still, I would have thought, a modern compiler could figure this out by itself
– old123987
Sep 9 '18 at 12:58
@old123987 the compiler did figure it out and warned you that the line was unreachable. =P
– Moohasha
Sep 9 '18 at 12:59
You mean aside from answering the question? The question was about a line being unreachable. This answer explained why and corrected it.
– Moohasha
Sep 9 '18 at 21:36
@ChefGladiator Casting a thing to void to suppress 'unused variable' warning is widely used pre-C++17 (and in C). It's not standard, but I wouldn't say it's "as far as one can get from standard portable C++". As far as I know, it's fairly portable and should work on most decent compilers.
– HolyBlackCat
Sep 9 '18 at 21:59
Where did OP say he was trying to write portable code?
– Moohasha
Sep 9 '18 at 22:15
As the direct answer to the direct question. On the subject of if constexpr
. Consider this:
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;
Depending on the bool result of the if constexpr
expression, compiler actually produces two functions. This version is produced when if constexpr()
yields true:
if constexpr
if constexpr()
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;
This version is produced when if constexpr()
yields false:
if constexpr()
template <typename T, typename ... params >
inline bool
match_monostate (std::variant<params ...> & variant) noexcept
return false;
The second version might emit warnings about unused argument. But (it seems) not if using the latest versions of clang/gcc/msvc. For older compilers as "old123987" also pointed out one can add the standard attribute to the signature. Like so:
template <typename T, typename ... params >
inline bool
match_monostate ([[maybe_unused]] std::variant<params ...> & variant) ;
That will stop the warning emitting.
Do you see any upside/downside in using std::variant<params...>& vs just VariantType& ? (besides type safety)
– old123987
Sep 10 '18 at 15:42
I can not see any obvious downside to the
match_monostate
signature, as presented. It will also stop you doing for example this: match_monostate( variant<int>);
or calling it with const instances ...– user10133158
Sep 11 '18 at 7:17
match_monostate
match_monostate( variant<int>);
As an anti jokers measure you can delete this declaration: ` template <typename ... params > inline bool match_monostate ( std::variant<params ...> && variant) ; = delete
, to stop them calling it with moved instances
match_monostate( move(var_))`– user10133158
Sep 11 '18 at 7:36
, to stop them calling it with moved instances
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
You do not need the
SUPRESS_C4100
"trick". See here: wandbox.org/permlink/zewgEt073tRV3dJV .. same is here on my machine with MSVC 19.15.26726– user10133158
Sep 9 '18 at 23:23