2020年11月19日

C++11以降の未使用の関数引数の書き方

追記:本記事の内容は C++98 から有効であるとコメント欄にて教えていただきました。情報提供に感謝いたします。

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) にキャストするという方法が一般的ですが面倒です。
$ 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.c
C++ の場合ならば、C++11 以降、コンパイラ拡張ではなく、正式な仕様で未使用引数の名前を省略するという書き方が許されました。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf
8.4 Function definitions
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 ]
しかしこれ、GCC でも Clang でも、C++98 や C++03 でも通ってしまいます。
$ 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.202
C だと当然エラーです。
$ 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) {}


kmckk at 16:36コメント(2)C++ | 若槻 

コメント一覧

1. Posted by 名無し   2021年03月09日 00:04
いいえ、その規定はISO/IEC 14882:1998の時点で存在しています
2. Posted by 若槻   2021年04月14日 17:46
なるほど、C++98 の規格書を持っていないため確認できませんが、情報ありがとうございます。それならば C++98 でも通るのは納得です。

コメントする

名前
 
  絵文字
 
 
記事検索
最新コメント
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード