Reputation: 102346
I'm experiencing an issue where a static member function uses an UNUSED
macro to silence compiler warnings. When the macro is in effect, it causes GCC and Clang to reject the function as a constexpr
. Here's the test case:
$ 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;
}
Here's the GCC error message:
$ 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
}
^
If I remove the use of UNUSED
, then the source file compiles as expected:
constexpr static size_t GetValidN(size_t n)
{
return DEF_N;
}
As far as I know, the #define UNUSED(x) ((void)x)
is the only portable way to suppress unused variable
warnings. I dread removing UNUSED
because the macro suppresses thousands of warnings in a non-trivial C++ project with lots of interfaces. I'm not even sure I can remove UNUSED
because of governance issues related to auditing and C&A.
How can I make the UNUSED
macro work and play well with constexpr
?
Clang produces a more helpful error message:
$ 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.
Another twist when moving from the clean room to production: Doxygen. This is closer to what happens in practice, so we can't omit the variable name.
//! \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;
}
Upvotes: 3
Views: 1098
Reputation: 50550
In C++11 you have some limitations on the body of a constexpr
function.
In your specific case you can use the comma operator to overcome them:
constexpr static size_t GetValidN(size_t n)
{
return UNUSED(n), DEF_N;
}
In C++14, your function is ok as it is.
Upvotes: 2
Reputation:
The simplest solution would be to just comment out the n as kfsone mentioned.
In C++17 you could even do it like this:
constexpr static size_t GetValidN([[maybe_unused]] size_t n)
{
return DEF_N;
}
For more information see http://en.cppreference.com/w/cpp/language/attributes
I'm not sure if this is a stylistically sane solution, hopefully IDEs will find a way to make it look less ugly.
Upvotes: 0