llvm / llvm/llvm-project

[libc++] Member types `argument_type`, `first_argument_type`, and `second_argument_type` of `reference_wrapper` are not correctly provided

Open
#169,973 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

libc++
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

It seems that libc++ hasn't implemented the rules in N4659 [depr.func.adaptor.typedefs]/4.3 and N4659 [depr.func.adaptor.typedefs]/5.3 at all.

Sometimes argument_type, first_argument_type, or second_argument_type are incorrectly provided due to inheritance form some base classes (unary_function and its friends) even if these names are shadowed in the derived class.
For some "normal" cases, these member types are basically missing when they were required to be provided.

Example (link)

#include <functional>
#include <type_traits>

struct S1 {
  using argument_type = void;
  using first_argument_type = int() const;
  using second_argument_type = char&&;
};

static_assert(std::is_same_v<std::reference_wrapper<S1>::argument_type, void>);
static_assert(std::is_same_v<std::reference_wrapper<S1>::first_argument_type, int() const>);
static_assert(std::is_same_v<std::reference_wrapper<S1>::second_argument_type, char&&>);

struct S2 : std::reference_wrapper<int(long)> {
  static constexpr int argument_type = 1729;
};

template <class T, class = void>
constexpr bool has_no_argument_type = true;
template <class T>
constexpr bool has_no_argument_type<T, std::void_t<typename T::argument_type>> = false;

static_assert(has_no_argument_type<std::reference_wrapper<S2>>);

struct S3 : std::reference_wrapper<void(int&, int&&)> {
  static constexpr int first_argument_type  = 421;
  static constexpr int second_argument_type = 729;
};

template <class T, class = void>
constexpr bool has_no_first_argument_type = true;
template <class T>
constexpr bool has_no_first_argument_type<T, std::void_t<typename T::first_argument_type>> = false;

template <class T, class = void>
constexpr bool has_no_second_argument_type = true;
template <class T>
constexpr bool has_no_second_argument_type<T, std::void_t<typename T::second_argument_type>> = false;

static_assert(has_no_first_argument_type<std::reference_wrapper<S3>>);
static_assert(has_no_second_argument_type<std::reference_wrapper<S3>>);

I'm not sure whether this is worth fixing because these member types were deprecated in C++17 and removed in C++20.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the std::reference_wrapper cases from the issue against libc++, then compare the observed member types with N4659 [depr.func.adaptor.typedefs]/4.3 and /5.3. Done means the static assertions pass, including suppression of inherited names when the wrapped type shadows them and provision of the required types in normal cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.