Невозможно скомпилировать вызов std :: Reduce, в то время как вызов std :: накопить компилируется с теми же параметрами - PullRequest
0 голосов
/ 18 октября 2019

Я пытался использовать c++17 std::reduce алгоритм. Предположительно, он должен поддерживать те же API, которые поддерживаются std::accumulate, но при компиляции в clang++-9.0 и gcc-9.2 с --std=c++17 вызов std::accumulate компилируется успешно, а вызов std::reduce - нет.

До сих пор я попробовал пару вещей:

  • Определение lambda как внутри, так и снаружи вызова
  • Явное указание типов с помощью std::reduce<...> синтаксис
  • Использование перегрузок с параметрами политики выполнения
    • Получены ошибки при #include <execution>

Ниже приведен пример кода, который используетstd::reduce и std::accumulate для суммирования длин строк в std::vector:

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <numeric>

int main() {
    auto op = [](auto acc, auto val) {
        return acc + val.size();
    };
    std::vector<std::string> v = {"a", "bb", "ccc", "dddd"};
    int a = std::reduce(v.begin(), v.end(), 0, op);
    int b = std::accumulate(v.begin(), v.end(), 0, op);
    return 0;
}

Сбой компиляции в строке, вызывающей std::reduce со следующим выводом из clang-9.0.0:

<source>:12:13: error: no matching function for call to 'reduce'

    int a = std::reduce(v.begin(), v.end(), 0, op);

            ^~~~~~~~~~~

/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/pstl/glue_numeric_defs.h:26:1: note: candidate template ignored: deduced conflicting types for parameter '_ForwardIterator' ('__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char> *, std::vector<std::__cxx11::basic_string<char>, std::allocator<std::__cxx11::basic_string<char> > > >' vs. 'int')

reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init);

^

/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/pstl/glue_numeric_defs.h:21:1: note: candidate function template not viable: requires 5 arguments, but 4 were provided

reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,

^

/opt/compiler-explorer/gcc-9.2.0/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../include/c++/9.2.0/pstl/glue_numeric_defs.h:31:1: note: candidate function template not viable: requires 3 arguments, but 4 were provided

reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last);

^

1 error generated.

и следующий вывод из gcc-9.2:

<source>: In function 'int main()':

<source>:12:50: error: no matching function for call to 'reduce(std::vector<std::__cxx11::basic_string<char> >::iterator, std::vector<std::__cxx11::basic_string<char> >::iterator, int, main()::<lambda(auto:1, auto:2)>&)'

   12 |     int a = std::reduce(v.begin(), v.end(), 0, op);

      |                                                  ^

In file included from /opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/numeric:229,

                 from <source>:5:

/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/pstl/glue_numeric_defs.h:21:1: note: candidate: 'template<class _ExecutionPolicy, class _ForwardIterator, class _Tp, class _BinaryOperation> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> std::reduce(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Tp, _BinaryOperation)'

   21 | reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,

      | ^~~~~~

/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/pstl/glue_numeric_defs.h:21:1: note:   template argument deduction/substitution failed:

<source>:12:50: note:   deduced conflicting types for parameter '_ForwardIterator' ('__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >' and 'int')

   12 |     int a = std::reduce(v.begin(), v.end(), 0, op);

      |                                                  ^

In file included from /opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/numeric:229,

                 from <source>:5:

/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/pstl/glue_numeric_defs.h:26:1: note: candidate: 'template<class _ExecutionPolicy, class _ForwardIterator, class _Tp> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _ForwardIterator2> std::reduce(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Tp)'

   26 | reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init);

      | ^~~~~~

/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/pstl/glue_numeric_defs.h:26:1: note:   template argument deduction/substitution failed:

<source>:12:50: note:   deduced conflicting types for parameter '_ForwardIterator' ('__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >' and 'int')

   12 |     int a = std::reduce(v.begin(), v.end(), 0, op);

      |                                                  ^

In file included from /opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/numeric:229,

                 from <source>:5:

/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/pstl/glue_numeric_defs.h:31:1: note: candidate: 'template<class _ExecutionPolicy, class _ForwardIterator> __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, typename std::iterator_traits<_II>::value_type> std::reduce(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator)'

   31 | reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last);

      | ^~~~~~

/opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/pstl/glue_numeric_defs.h:31:1: note:   template argument deduction/substitution failed:

<source>:12:50: note:   deduced conflicting types for parameter '_ForwardIterator' ('__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >' and 'int')

   12 |     int a = std::reduce(v.begin(), v.end(), 0, op);

      |                                                  ^

Ответы [ 2 ]

1 голос
/ 09 ноября 2019

На самом деле, одно из различий между reduce и accumulate заключается в поддержке политик выполнения. Если вам не нужны политики выполнения, вы можете позвонить accumulate. Итак, код с std::execution::seq успешно компилируется с gcc-trunk: https://godbolt.org/z/ERxU_q

0 голосов
/ 18 октября 2019

Как прокомментировал @ Vittorio Romeo , это, вероятно, ошибка или еще не реализованная функция в libstc++, и ее можно использовать, переключившись на libc++ с помощью -libstd=libc++

...