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

履歴 編集

function template
<utility>

std::forward_like(C++23)

namespace std {
  template <class T, class U>
  [[nodiscard]] constexpr auto forward_like(U&& x) noexcept -> see-below;
}

概要

第一テンプレート引数のconst性と参照修飾を用いて関数テンプレートの引数を転送する。

この関数は主に、クラスオブジェクトのconst性と参照修飾を用いてメンバ変数を転送する目的で使用される。

効果

  • COPY_CONST(A, B)Aconst修飾されているときconst B、そうでないときBとする
  • OVERRIDE_REF(A, B)Aが右辺値参照のときremove_reference_t<B>&&、そうでないときB&とする
  • VOVERRIDE_REF(T&&, COPY_CONST(remove_reference_t<T>, remove_reference_t<U>))とする

以上のもとで、forward_likestatic_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

処理系

参照