检查布尔模板参数时摆脱“条件表达式为常数”警告的方法?

Posted

技术标签:

【中文标题】检查布尔模板参数时摆脱“条件表达式为常数”警告的方法?【英文标题】:Ways to get rid of "conditional expression is constant" warning when checking bool template parameter? 【发布时间】:2015-02-06 22:43:32 【问题描述】:

当使用 /W4 (MSVC 2013) 编译时,此代码模板会产生“条件表达式为常量”警告:

#include <iostream>

template <bool condition>
struct Conditional

    static void f()
    
        if (condition)
            std::cout << "true";
        else
            std::cout << "false";
    
;

void main()

    Conditional<false>::f();

现在,假设Conditional 实际上是一个有用的类,它有很多方法和条件周围的大量代码。我想通过尽可能少的代码修改来消除警告。

我知道的唯一一个技巧是标签调度。这是可以接受的,但有点笨拙,因为我需要声明 2 个额外的方法并在那里提取条件代码。还有其他方法吗?

【问题讨论】:

标签调度听起来有点矫枉过正。您是说模板专业化吗? 我在 Java 中解决这个问题的方法是我有一个全局可见的静态 get 函数,它接受任何东西作为参数并原封不动地返回它。因此,代码将如下所示:if( get( condition ) ) ... 由于编译器不知道函数是如何工作的,它不再将条件视为常量。你不能在 C++ 中做类似的事情吗? @DrewDormann:我的意思是标签调度;专业化看起来确实非常适合这种情况。 @MikeNakis:我可以,但真的很难看! 我很想打赌它一定是替代品中最不丑的。您可以将其包装在一个宏中,该宏在编译发布时扩展为参数本身(无函数调用)。 【参考方案1】:

你可以使用专业化:

template <bool condition>
struct Conditional

    static void f();
;

template <>
void Conditional<true>::f()  std::cout << "true"; 

template <>
void Conditional<false>::f()  std::cout << "false"; 

Live example

【讨论】:

可能是一个愚蠢的问题,但如果bool 不是唯一的模板参数,我仍然可以这样做,对吧?那将是部分专业化?如果f() 是非静态虚拟方法,它仍然可以正常工作吗? 实际上,如果特化是显式特化,您只能将方法与特化定义内联。否则(如果是部分的)你必须先定义类的特化,然后再改变方法。 ^ 因为函数没有部分特化【参考方案2】:

在 C++17 及更高版本中,if constexpr 解决了这个问题:

#include <iostream>

template <bool condition>
struct Conditional

    static void f()
    
        if constexpr (condition) // No warning because the branch is calculated 
                                 // at compile time and not present at runtime.
            std::cout << "true";
        else
            std::cout << "false";
    
;

void main()

    Conditional<false>::f();

【讨论】:

以上是关于检查布尔模板参数时摆脱“条件表达式为常数”警告的方法?的主要内容,如果未能解决你的问题,请参考以下文章

将值强制为布尔值:(bool) 发出警告,!!不

Scala 2.12.2 发出大量无用的“警告:参数值...在方法中...从未使用过”警告。如何摆脱它们?

尝试使用router.history.goBack与react-router时获得警告

vue 警告:无效的道具:道具“modalState”的类型检查失败。预期布尔值,得到函数

通过负面警告摆脱 gcc shift

如何摆脱盲目的sql注入?