3

我遇到了一个静态成员函数使用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.

从洁净室到生产的另一个转折点:Doxygen。这更接近于实际发生的情况,因此我们不能省略变量名。

//! \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;
}
4

3 回答 3

3

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

constexpr size_t DEF_N = 42;

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

现场演示

于 2016-09-05T06:17:36.443 回答
2

constexpr在 C++11 中,您对函数体有一些限制。

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

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

在 C++14 中,您的函数可以正常运行。

于 2016-09-05T06:11:00.043 回答
0

最简单的解决方案是只注释掉 kfsone 提到的 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 能找到一种方法让它看起来不那么难看。

于 2016-09-05T06:24:46.610 回答