読者です 読者をやめる 読者になる 読者になる

C++1z 関数が呼び出し可能かを判定する型特性

C++

C++1zからは、関数が呼び出せるかどうかをコンパイル時に判定する型特性として、is_callableis_nothrow_callableの2つが<type_traits>に追加されます。

// <type_traits>
namespace std {
    template <class, class R = void> struct is_callable; // 宣言のみ
    template <class Fn, class... ArgTypes, class R>
        struct is_callable<Fn(ArgTypes...), R>;

    template <class, class R = void> struct is_nothrow_callable; // 宣言のみ
    template <class Fn, class... ArgTypes, class R>
        struct is_nothrow_callable<Fn(ArgTypes...), R>;

    // 変数テンプレート版
    template <class T, class R = void>
    constexpr bool is_callable_v = is_callable<T, R>::value;

    template <class T, class R = void>
    constexpr bool is_nothrow_callable_v = is_nothrow_callable<T, R>::value;
}

is_callableは、関数を呼び出せる場合にはtrue_type、呼び出せない場合にはfalse_typeから派生します。

is_nothrow_callableは、関数が例外を投げずに(noexcept(true))呼び出せる場合にはtrue_type、そうでない場合にはfalse_typeから派生します。

これらの型特性はテンプレートパラメータとして、以下をとります:

  1. 関数のシグニチャ(関数の型と引数の型リストを合わせたもの)
  2. 戻り値の型
#include <type_traits>

struct F {
    int operator()(int, double) { return 1; }
};

struct G {
    int operator()(int, double) noexcept { return 2; }
};

int main()
{
    static_assert(std::is_callable<F(int, double), int>::value);
    static_assert(std::is_callable<G(int, double), int>::value);

    // Gの関数呼び出し演算子はnoexceptなので、trueとなる
    static_assert(std::is_nothrow_callable<F(int, double), int>::value == false);
    static_assert(std::is_nothrow_callable<G(int, double), int>::value);

    // 変数テンプレート版は::valueを指定する必要がない
    static_assert(std::is_callable_v<F(int, double), int>);
}

参照

お断り

この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。