• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

    最終更新日時(UTC):
    が更新

    履歴 編集

    class template
    <functional>

    std::move_only_function

    namespace std {
      template<class... S>
      class move_only_function; // 宣言のみ
    
      template<class R, class... ArgTypes>
      class move_only_function<R(ArgTypes...) /*cv*/ /*ref*/ noexcept(/*noex*/)>;
    }
    

    概要

    move_only_functionクラステンプレートは、パラメータの型リストArgTypes...戻り値の型Rに合致する、あらゆる関数ポインタ、関数オブジェクト、メンバ関数ポインタ、メンバ変数ポインタを保持できるクラスである。

    下記全ての組み合わせ(12種類)に対して、クラステンプレートの部分特殊化が提供される。

    • CV修飾cv : const, CV修飾無し
    • 参照修飾子 ref : &, &&, 参照修飾無し
    • noexcept例外指定 noex : true, false

    functionとの比較

    std::functionと比べて、std::move_only_functionは下記の特徴をもつ。

    • ムーブのみ対応。コピー不可。
    • 関数型のCV修飾/参照修飾/noexcept例外指定をサポートする。
      • const性などを正しく伝搬することでバグ発生リスクを軽減する
    • target_type型とtarget()を提供しない。
      • 実行時型情報(RTTI)非依存
    • 関数呼び出しは強い事前条件を持つ。
      • 関数呼び出し時のnullチェックが要求されない
    • クラステンプレート引数の推論補助を提供しない。

    メンバ関数

    名前 説明 対応バージョン
    (constructor) コンストラクタ C++23
    (destructor) デストラクタ C++23
    operator= 代入演算子 C++23
    swap 他のmove_only_functionオブジェクトと中身を入れ替える C++23
    operator bool 関数呼び出しが可能か調べる C++23
    operator() 関数呼び出し C++23

    メンバ型

    名前 説明 対応バージョン
    result_type 関数の戻り値の型(テンプレートパラメータR) C++23

    非メンバ関数

    名前 説明 対応バージョン
    operator== 等値比較 C++23
    operator!= 非等値比較 C++23
    swap 2つのmove_only_functionオブジェクトを入れ替える C++23

    例1: 基本の使い方

    #include <functional>
    #include <iostream>
    
    int add(int x) { return x + 1; }
    
    int main()
    {
      // 関数を代入
      std::move_only_function<int(int)> f = add;
    
      // 関数オブジェクトを代入
      f = [](int x) { return x + 1; };
    
      // 保持している関数を呼び出す
      int result = f(1);
      std::cout << result << std::endl;
    }
    

    出力

    2
    

    例2: const性の伝搬

    #include <functional>
    #include <iostream>
    #include <string>
    #include <utility>
    
    struct Functor {
      std::string operator()() {
        return "non-const";
      }
      std::string operator()() const {
        return "const";
      }
    };
    
    int main()
    {
      std::cout << "-- move_only_function" << std::endl;
            std::move_only_function<std::string(void)>       mof1 = Functor{};
      const std::move_only_function<std::string(void)>       mof2 = Functor{}; // (呼び出し時に不適格)
            std::move_only_function<std::string(void) const> mof3 = Functor{};
      const std::move_only_function<std::string(void) const> mof4 = Functor{};
      std::cout << "mof1: " << mof1() << std::endl;
    //std::cout << "mof2: " << mof2() << std::endl; // 不適格
      std::cout << "mof3: " << mof3() << std::endl;
      std::cout << "mof4: " << mof4() << std::endl;
    
      std::cout << "-- function" << std::endl;
            std::function<std::string(void)>       fn1 = Functor{};
      const std::function<std::string(void)>       fn2 = Functor{};
    //      std::function<std::string(void) const> fn3 = Functor{}; // 不適格
    //const std::function<std::string(void) const> fn4 = Functor{}; // 不適格
      std::cout << "fn1: " << fn1() << std::endl;
      std::cout << "fn2: " << fn2() << std::endl;
    }
    

    出力

    -- move_only_function
    mof1: non-const
    mof3: const
    mof4: const
    -- function
    fn1: non-const
    fn2: non-const
    

    例3: 左辺値/右辺値の伝搬

    #include <functional>
    #include <iostream>
    #include <string>
    #include <utility>
    
    struct Functor {
      std::string operator()() & {
        return "L-val";
      }
      std::string operator()() && {
        return "R-val";
      }
    };
    
    int main()
    {
      std::cout << "-- move_only_function" << std::endl;
      std::move_only_function<std::string(void)>    mof1 = Functor{};
      std::move_only_function<std::string(void) &&> mof2 = Functor{};
      std::cout << "mof1/L-val: " << mof1()            << std::endl;
      std::cout << "mof1/R-val: " << std::move(mof1)() << std::endl;
    //std::cout << "mof2/L-val: " << mof2()            << std::endl; // 不適格
      std::cout << "mof2/R-val: " << std::move(mof2)() << std::endl;
    
      std::cout << "-- function" << std::endl;
      std::function<std::string(void)>    fn1 = Functor{};
    //std::function<std::string(void) &&> fn2 = Functor{}; // 不適格
      std::cout << "fn1/L-val: " << fn1()            << std::endl;
      std::cout << "fn1/R-val: " << std::move(fn1)() << std::endl;
    }
    

    出力

    -- move_only_function
    mof1/L-val: L-val
    mof1/R-val: L-val
    mof2/R-val: R-val
    -- function
    fn1/L-val: L-val
    fn1/R-val: L-val
    

    例4: noexcept指定の伝搬

    #include <functional>
    
    void func() {}
    void func_noex() noexcept {}
    
    int main()
    {
      std::move_only_function<void(void)>          mof1 = func;
      std::move_only_function<void(void)>          mof2 = func_noex;
    //std::move_only_function<void(void) noexcept> mof3 = func; // 不適格
      std::move_only_function<void(void) noexcept> mof4 = func_noex;
      static_assert(not noexcept(mof1()));
      static_assert(not noexcept(mof2()));
      static_assert(    noexcept(mof4()));
    
      std::function<void(void)>          fn1 = func;
      std::function<void(void)>          fn2 = func_noex;
    //std::function<void(void) noexcept> fn3 = func;      // 不適格
    //std::function<void(void) noexcept> fn4 = func_noex; // 不適格
      static_assert(not noexcept(fn1()));
      static_assert(not noexcept(fn2()));
    }
    

    出力

    バージョン

    言語

    • C++23

    処理系

    関連項目

    参照