namespace std {
template <class T, class U>
[[nodiscard]] constexpr auto forward_like(U&& x) noexcept -> see-below;
}
概要
第一テンプレート引数のconst
性と参照修飾を用いて関数テンプレートの引数を転送する。
この関数は主に、クラスオブジェクトのconst
性と参照修飾を用いてメンバ変数を転送する目的で使用される。
効果
COPY_CONST(A, B)
をA
がconst
修飾されているときconst B
、そうでないときB
とするOVERRIDE_REF(A, B)
をA
が右辺値参照のときremove_reference_t<B>&&
、そうでないときB&
とするV
をOVERRIDE_REF(T&&, COPY_CONST(remove_reference_t<T>, remove_reference_t<U>))
とする
以上のもとで、forward_like
はstatic_cast<V>(x)
を返す。
例外
投げない
備考
戻り値の型はV
である。
例
効果の確認
#include <type_traits>
#include <utility>
int main()
{
int a = 0;
int& b1 = a;
int&& b2 = 0;
const int& b3 = a;
const int&& b4 = 0;
static_assert(std::is_same_v<decltype(std::forward_like<decltype(b1)>(a)), int&>);
static_assert(std::is_same_v<decltype(std::forward_like<decltype(b2)>(a)), int&&>);
static_assert(std::is_same_v<decltype(std::forward_like<decltype(b3)>(a)), const int&>);
static_assert(std::is_same_v<decltype(std::forward_like<decltype(b4)>(a)), const int&&>);
}
出力
基本的な使用例 (not_fn
の再実装)
#include <functional>
#include <iostream>
#include <string>
#include <type_traits>
#include <utility>
template <class F>
struct not_fn_t {
F f;
template <class Self, class... Args>
constexpr auto operator()(this Self&& self, Args&&... args) noexcept(
noexcept( !std::invoke(std::forward_like<Self>(self.f), std::forward<Args>(args)...)))
-> decltype(!std::invoke(std::forward_like<Self>(self.f), std::forward<Args>(args)...)) {
return !std::invoke(std::forward_like<Self>(self.f), std::forward<Args>(args)...);
}
};
template <class F>
constexpr not_fn_t<std::decay_t<F>> my_not_fn(F&& f) {
return {std::forward<F>(f)};
}
int main()
{
constexpr auto non_empty = my_not_fn(&std::string::empty);
std::string str = "str";
std::cout << std::boolalpha << non_empty(str) << std::endl;
}
出力
true
実装例
template <class A, class B>
using __copy_const_t = conditional_t<is_const_v<A>, const B, B>;
template <class A, class B>
using __override_ref_t =
conditional_t<is_rvalue_reference_v<A>, remove_reference_t<B>&&, B&>;
template <class T, class U>
using __forward_like_t = __override_ref_t<
T&&, __copy_const_t<remove_reference_t<T>, remove_reference_t<U>>>;
template <class T, class U>
[[nodiscard]] constexpr auto forward_like(U&& x) noexcept
-> __forward_like_t<T, U> {
return static_cast<__forward_like_t<T, U>>(x);
}
バージョン
言語
- C++23
処理系
- Clang: 16.0.0 ✅
- GCC: ??
- ICC: ??
- Visual C++: 2022 17.4 ✅