Почему std :: function работает как аргумент для std :: not2? - PullRequest
3 голосов
/ 09 июля 2020

std :: not2 реализуется следующим образом:

template <class Predicate>
binary_negate<Predicate> not2 (const Predicate& pred)
{
    return binary_negate<Predicate>(pred);
}

Он использует std :: binary_negate в своей реализации, а binary_negate, унаследованный от std :: binary_function, требует _Predicate :: first_argument_type и _Predicate: : second_argument_type в своих шаблонных аргументах следующим образом:

template <class _Predicate>
class binary_negate : public binary_function<typename _Predicate::first_argument_type,
                                             typename _Predicate::second_argument_type,
                                             bool>
{
    // ...
}

И мой вопрос в том, почему я могу написать что-то подобное, если в передаваемом мной предикате нет typedefs для first_argument_type и second_argument_type?

struct new_same
{
    bool operator()(int a, int b) const { return a == b; }
};
auto not_same = std::not2(std::function<bool(int, int)>(new_same()));

Ответы [ 3 ]

1 голос
/ 09 июля 2020

Согласно cppreference :

not2 - это вспомогательная функция для создания объекта функции, который возвращает дополнение переданной двоичной функции-предиката. Созданный объект функции имеет тип std::binary_negate<Predicate>.

и:

Тип двоичного предиката должен определять два типа членов, first_argument_type и second_argument_type, которые преобразуются в типы параметров предиката. Функциональные объекты, полученные из [...] std::function или из другого вызова std::not2, имеют эти типы, определенные, как и функциональные объекты, производные от устаревшего std::binary_function .

В моей реализации (MinGW с G CC 9.2.0) std::function происходит от _Maybe_unary_or_binary_function, которое при создании экземпляра с двумя аргументами происходит от std::binary_function.

Обратите внимание, что эта функция устарела . К сожалению, сейчас я не могу найти ему замену.

1 голос
/ 09 июля 2020

Существует также (из cppreference ):

template< class Predicate >           (since C++11)
struct binary_negate;                 (deprecated in C++17)
                                      (removed in C++20)

Кроме того, std::function действительно имеет следующие typdef:

first_argument_type    (deprecated in C++17)(removed in C++20)
second_argument_type   (deprecated in C++17)(removed in C++20)

почему я могу написать что-то подобное, если в переданном мной предикате нет typedefs для first_argument_type и second_argument_type?

Здесь есть typedef. binary_negate может получить их из Predicate (в вашем случае это std::function).

Все это устарело в C++17 и удалено в C++20. Должен признать, что не могу сказать вам, что это за замена.

0 голосов
/ 09 июля 2020

Если вы посмотрите на реализацию std :: function, вы увидите, что она наследует класс с именем _Maybe_unary_or_binary_function. Это наследование заставляет std :: function наследовать std :: binary_function, если количество параметров равно двум.

  template<typename _Res, typename... _ArgTypes>
    class function<_Res(_ArgTypes...)>
    : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>,
      private _Function_base
    {
        ...
    }
  template<typename _Res, typename... _ArgTypes>
    struct _Maybe_unary_or_binary_function { };

  /// Derives from @c unary_function, as appropriate.
  template<typename _Res, typename _T1>
    struct _Maybe_unary_or_binary_function<_Res, _T1>
    : std::unary_function<_T1, _Res> { };

  /// Derives from @c binary_function, as appropriate.
  template<typename _Res, typename _T1, typename _T2>
    struct _Maybe_unary_or_binary_function<_Res, _T1, _T2>
    : std::binary_function<_T1, _T2, _Res> { };

путем наследования от std :: binary_function, first_argument_type и second_argument_type добавляются к std: : функция:

template<typename _Arg1, typename _Arg2, typename _Result>
 struct binary_function
    {
      /// @c first_argument_type is the type of the first argument
      typedef _Arg1     first_argument_type; 

      /// @c second_argument_type is the type of the second argument
      typedef _Arg2     second_argument_type;

      /// @c result_type is the return type
      typedef _Result   result_type;
    };
...