如何使用 UNUSED 宏来消除 CONSTEXPR 函数中的警告?
How to use UNUSED macro to silence warning within a CONSTEXPR function?
我遇到了静态成员函数使用 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++ 项目中抑制了数千条警告。由于与审计和 C&A 相关的治理问题,我什至不确定我是否可以删除 UNUSED
。
我怎样才能使 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;
}
在 C++11 中,您对 constexpr
函数的主体有一些限制。
在您的特定情况下,您可以使用逗号运算符来克服它们:
constexpr static size_t GetValidN(size_t n)
{
return UNUSED(n), DEF_N;
}
在 C++14 中,您的函数就可以了。
您可以简单地避免给参数命名,或将其注释掉:
constexpr size_t DEF_N = 42;
constexpr static size_t GetValidN(size_t /*n*/)
{
return DEF_N;
}
最简单的解决方案是像 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 能找到一种方法让它看起来不那么难看。
我遇到了静态成员函数使用 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++ 项目中抑制了数千条警告。由于与审计和 C&A 相关的治理问题,我什至不确定我是否可以删除 UNUSED
。
我怎样才能使 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;
}
在 C++11 中,您对 constexpr
函数的主体有一些限制。
在您的特定情况下,您可以使用逗号运算符来克服它们:
constexpr static size_t GetValidN(size_t n)
{
return UNUSED(n), DEF_N;
}
在 C++14 中,您的函数就可以了。
您可以简单地避免给参数命名,或将其注释掉:
constexpr size_t DEF_N = 42;
constexpr static size_t GetValidN(size_t /*n*/)
{
return DEF_N;
}
最简单的解决方案是像 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 能找到一种方法让它看起来不那么难看。