如何使用未使用的宏在CONSTEXPR函数中沉默警告

How to use UNUSED macro to silence warning within a CONSTEXPR function?

本文关键字:函数 沉默 警告 CONSTEXPR 何使用 未使用      更新时间:2023-10-16

我遇到一个静态成员函数使用UNUSED宏来沉默编译器警告的问题。当宏生效时,它会导致GCC和Clang将该函数作为constexpr拒绝。下面是测试用例:

$ cat test.cxx
#include <iostream>
#include <stdint.h>
#define UNUSED(x) ((void)x)
template <unsigned int N>
class Foo
{
public:
    enum {MIN_N=N}; enum {MAX_N=N}; enum {DEF_N=N};
    constexpr static size_t GetValidN(size_t n)
    {
        UNUSED(n); return DEF_N;
    }
};
class Bar : public Foo<16>
{
public:
    Bar(size_t n) : m_n(GetValidN(n)) {}
    size_t m_n;
};
int main(int argc, char* argv[])
{
    Bar b(10);
    return 0;
}

下面是GCC的错误信息:

$ g++ -std=c++11 test.cxx -o test.exe
test.cxx: In instantiation of ‘static constexpr size_t Foo<N>::GetValidN(size_t) [with unsigned int N = 16u; size_t = long unsigned int]’:
test.cxx:22:25:   required from here
test.cxx:16:5: error: body of constexpr function ‘static constexpr size_t Foo<N>::GetValidN(size_t) [with unsigned int N = 16u; size_t = long unsigned int]’ not a return-statement
     }
     ^

如果我删除使用UNUSED,则源文件按预期编译:

constexpr static size_t GetValidN(size_t n)
{
    return DEF_N;
}

据我所知,#define UNUSED(x) ((void)x)是唯一可移植的方法来抑制 unused variable 警告。我害怕删除UNUSED,因为在具有大量接口的重要c++项目中,宏会抑制数千个警告。我甚至不确定我是否可以删除UNUSED,因为与审计和C& a相关的治理问题。

我如何使UNUSED宏工作和constexpr发挥良好?


Clang产生一个更有用的错误消息:

$ clang++ -std=c++11 test.cxx -o test.exe
test.cxx:15:2: warning: use of this statement in a constexpr function is a C++14
      extension [-Wc++14-extensions]
        UNUSED(n); return DEF_N;
        ^
test.cxx:4:19: note: expanded from macro 'UNUSED'
#define UNUSED(x) ((void)x)
                  ^
1 warning generated.

从洁净室转移到生产时的另一个问题:氧气。这更接近实际情况,所以我们不能省略变量名。

//! brief Returns a valid N
//! param n a value to determine a valid N
//! returns a valid N
constexpr static size_t GetValidN(size_t n)
{
    return DEF_N;
}

您可以简单地避免给参数命名,或者将其注释掉:

constexpr size_t DEF_N = 42;
constexpr static size_t GetValidN(size_t /*n*/)
{
    return DEF_N;
}

现场演示

在c++ 11中,constexpr函数体有一些限制。

在特定情况下,您可以使用逗号操作符来克服它们:

constexpr static size_t GetValidN(size_t n)
{
    return UNUSED(n), DEF_N;
}

在c++ 14中,你的函数是可以的

最简单的解决方案就是像kfsome提到的那样,把n注释掉。

在c++ 17中,你甚至可以这样做:

constexpr static size_t GetValidN([[maybe_unused]] size_t n)
{
    return DEF_N;
}

更多信息请参见http://en.cppreference.com/w/cpp/language/attributes

我不确定这是否是一个风格上合理的解决方案,希望ide能找到一种方法使它看起来不那么难看。