если constexpr и C4702 (и C4100, и C4715) - PullRequest
0 голосов
/ 09 сентября 2018

Есть ли способ решить следующую проблему:

Этот код выдает предупреждение 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 «не все пути управления возвращают значение».

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Как прямой ответ на прямой вопрос.По теме 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;
 }
}

В зависимости от результата bool выражения 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) ;

Это остановит выдачу предупреждения.

0 голосов
/ 09 сентября 2018

Это недоступно, потому что для данного расширения шаблона, основанного на аргументах шаблона, функция only когда-либо пройдет условие и вернет true или fail и вернет false. Нет ни одного случая, когда это могло бы пойти так или иначе для одного и того же типа. Это существенно расширяется до

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

Я бы переписал его только для одного оператора возврата.

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.

...