- functional[meta header]
- class template[meta id-type]
- std[meta namespace]
- cpp23[meta cpp]
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
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 |
#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;
}
- std::move_only_function[color ff0000]
- f(1)[link move_only_function/op_call.md]
2
#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;
}
- std::move_only_function[color ff0000]
- std::function[link function.md]
-- move_only_function
mof1: non-const
mof3: const
mof4: const
-- function
fn1: non-const
fn2: non-const
#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;
}
- std::move_only_function[color ff0000]
- std::function[link function.md]
-- 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
#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()));
}
- std::move_only_function[color ff0000]
- std::function[link function.md]
- C++23
- Clang: ??
- GCC: 12.1 [mark verified]
- ICC: ??
- Visual C++: ??
- C++11
function
- C++26
copyable_function
- C++26
copyable_function
- P0288R9 move_only_function
- N4348 Making
std::function
safe for concurrencystd::function
のconst性伝搬に関して、スレッドセーフ保証の観点からの問題指摘。
- Why does C++23 std::move_only_function not have deduction guides?