2020年11月19日
C++11以降の未使用の関数引数の書き方
追記:本記事の内容は C++98 から有効であるとコメント欄にて教えていただきました。情報提供に感謝いたします。
GCC でコンパイル時に -Wall -Wextra の 2 オプションを付けるというのは非常に一般的です。この場合、以下のように未使用の関数引数には警告が出ます。
GCC でコンパイル時に -Wall -Wextra の 2 オプションを付けるというのは非常に一般的です。この場合、以下のように未使用の関数引数には警告が出ます。
$ cat test.c void f(int x) {} void g(int x) {} int main() { f(10); g(10); return 0; } $ gcc -Wall -Wextra test.c test.c: In function ‘f’: test.c:1:12: warning: unused parameter ‘x’ [-Wunused-parameter] void f(int x) {} ^ test.c: In function ‘g’: test.c:2:12: warning: unused parameter ‘x’ [-Wunused-parameter] void g(int x) {} ^しかし、例えばコールバックとして渡す関数(ハンドラ)のように、引数を全部使わない関数というのはよくあります。
C の場合は、GCC の attribute を使うか、(void) にキャストするという方法が一般的ですが面倒です。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf
https://google.github.io/styleguide/cppguide.html
$ cat test2.c void f(__attribute__((unused)) int x) {} void g(int x) { (void)x; } int main() { f(10); g(10); return 0; } $ gcc -Wall -Wextra test2.cC++ の場合ならば、C++11 以降、コンパイラ拡張ではなく、正式な仕様で未使用引数の名前を省略するという書き方が許されました。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf
8.4 Function definitionsしかしこれ、GCC でも Clang でも、C++98 や C++03 でも通ってしまいます。
8.4.1 In general
6 [ Note: Unused parameters need not be named. For example,void print(int a, int) { std::printf("a = %d\n",a); }end note ]
$ cat test.cpp void f(int) {} void g(int) {} int main() { f(10); g(10); return 0; } $ clang++ -std=c++98 -Wall -Wextra test.cpp $ clang++ -std=c++03 -Wall -Wextra test.cpp $ clang++ -std=c++11 -Wall -Wextra test.cpp $ g++ -std=c++98 -Wall -Wextra test.cpp $ g++ -std=c++03 -Wall -Wextra test.cpp $ g++ -std=c++11 -Wall -Wextra test.cpp $ g++ -v gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04) $ clang++ -v Ubuntu clang version 10.0.1-++20201112101950+ef32c611aa2-1~exp1~20201112092551.202C だと当然エラーです。
$ cat test3.c void f(int) {} void g(int) {} int main() { f(10); g(10); return 0; } $ gcc -Wall -Wextra test3.c test3.c: In function ‘f’: test3.c:1:1: error: parameter name omitted void f(int) {} ^~~~ test3.c: In function ‘g’: test3.c:2:1: error: parameter name omitted void g(int) {} ^~~~ただし、これを安易に多用すると、引数の意味がわかりにくくなります。Google C++ Style Guide では、自明なもの以外はコメントとして引数名を書くべき(should)としています。
https://google.github.io/styleguide/cppguide.html
Unused parameters that are obvious from context may be omitted:class Foo { public: Foo(const Foo&) = delete; Foo& operator=(const Foo&) = delete; };Unused parameters that might not be obvious should comment out the variable name in the function definition:class Shape { public: virtual void Rotate(double radians) = 0; }; class Circle : public Shape { public: void Rotate(double radians) override; }; void Circle::Rotate(double /*radians*/) {}// Bad - if someone wants to implement later, it's not clear what the // variable means. void Circle::Rotate(double) {}