Re[2]: ranges ?
От: Chorkov Россия  
Дата: 20.02.20 16:07
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Уважаемые коллеги, а кто-нибудь может показать решение этого вопроса с помощью ranges?


Ranges немного для другого.
С их помощью можно, например, улучшить сообшщения об ошибках. (Получать их в точке инстационирования шаблонной функции, а не в ее внутренностях.)
Но если постараться, то можно и так...

#include <iostream>
#include <vector>
#include <array>
#include <ranges>
#include <algorithm>
#include <string>
#include <concepts>

using namespace std::literals::string_literals;

// concepts-style
template<typename T, std::ranges::range Container>
     requires requires (const T& value,  const Container& cnt) { value==*std::begin(cnt); }  // Можно как-то по проще написать?
bool in_range( const T& value,  const Container& cnt )
{
    return std::ranges::find( cnt, value ) != std::ranges::end( cnt );
}



// old-style
template<typename T, typename Container>
auto in_any_container( const T& value,  const Container& cnt )
    -> decltype( value== *std::begin(cnt) ) // hand-make constrait!
{
    for( auto& v : cnt )
        if(v==value)
            return true;
    return false;
}


int main()
{
// Success cases:
    std::vector<int> vect{1,2,3};
    std::cout<< in_range(1, vect ) <<std::endl;
    std::cout<< in_any_container(1, vect ) <<std::endl;
    std::cout<< std::ranges::count( vect, 1 ) <<std::endl;
    
    
    int c_array[]={1,2,3};
    std::cout<< in_range(1, c_array ) <<std::endl;
    std::cout<< in_any_container(1, c_array ) <<std::endl;
    std::cout<< std::ranges::count( c_array, 1 ) <<std::endl;
    
    
    std::cout<< in_range(1, std::initializer_list{1,2,3} ) <<std::endl;
    std::cout<< in_any_container(1, std::initializer_list{1,2,3} ) <<std::endl;
    std::cout<< std::ranges::count( std::initializer_list{1,2,3}, 1 ) <<std::endl;
    
    std::cout<< in_range(1,         std::array{1,2,3} ) <<std::endl;
    std::cout<< in_any_container(1, std::array{1,2,3} ) <<std::endl;
    std::cout<< std::ranges::count( std::array{1,2,3}, 1 ) <<std::endl;
    
// Error cases:

    std::cout<< in_range("1"s,         vect       ) <<std::endl;
/*
prog.cc: In function 'int main()':
prog.cc:58:51: error: no matching function for call to 'in_range(std::__cxx11::basic_string<char>, std::vector<int>&)'
   58 |     std::cout<< in_range("1"s,         vect       ) <<std::endl;
      |                                                   ^
prog.cc:14:6: note: candidate: 'bool in_range(const T&, const Container&) [with T = std::__cxx11::basic_string<char>; Container = std::vector<int>]'
   14 | bool in_range( const T& value,  const Container& cnt )
      |      ^~~~~~~~    
...
*/

    std::cout<< in_any_container("1"s, vect       ) <<std::endl;
/*
prog.cc: In function 'int main()':
prog.cc:59:51: error: no matching function for call to 'in_any_container(std::__cxx11::basic_string<char>, std::vector<int>&)'
   59 |     std::cout<< in_any_container("1"s, vect       ) <<std::endl;
      |                                                   ^
prog.cc:23:6: note: candidate: 'template<class T, class Container> decltype ((value == (* std::begin(cnt)))) in_any_container(const T&, const Container&)'
   23 | auto in_any_container( const T& value,  const Container& cnt )
      |      ^~~~~~~~~~~~~~~~
...
*/
    std::cout<< std::ranges::count(    vect, "1"s ) <<std::endl;
/*
prog.cc: In function 'int main()':
prog.cc:60:51: error: no match for call to '(const std::ranges::__count_fn) (std::vector<int>&, std::__cxx11::basic_string<char>)'
   60 |     std::cout<< std::ranges::count(    vect, "1"s ) <<std::endl;
      |                                                   ^
In file included from /opt/wandbox/gcc-head/include/c++/10.0.1/algorithm:64,
                 from prog.cc:5:
/opt/wandbox/gcc-head/include/c++/10.0.1/bits/ranges_algo.h:369:7: note: candidate: 'template<class _Iter, class _Sent, class _Tp, class _Proj>  requires (input_iterator<_Iter>) && (sentinel_for<_Sent, _Iter>) && (indirect_binary_predicate<std::ranges::equal_to, std::projected<_I1, _P1>, const _Tp*>) constexpr std::iter_difference_t<_Iter> std::ranges::__count_fn::operator()(_Iter, _Sent, const _Tp&, _Proj) const'
  369 |       operator()(_Iter __first, _Sent __last,
      |       ^~~~~~~~
*/

    return 0;
}
Re[3]: ranges ?
От: B0FEE664  
Дата: 20.02.20 16:30
Оценка:
Здравствуйте, Chorkov, Вы писали:

BFE>>Уважаемые коллеги, а кто-нибудь может показать решение этого вопроса с помощью ranges?

C>Ranges немного для другого.

Странно. Я ожидал чего-то такого:
if ( {1,2,4,6,7} | std::ranges::count(x) )
  ....

или
if ( ({1,2,4,6,7} | std::views::filter([x](int i){ return x == i; })).size() )
  ....

так или как-то так нельзя?
И каждый день — без права на ошибку...
Re[4]: ranges ?
От: rg45 СССР  
Дата: 20.02.20 19:22
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Странно. Я ожидал чего-то такого:

BFE>
BFE>if ( {1,2,4,6,7} | std::ranges::count(x) )
BFE>  ....
BFE>

BFE>или
BFE>
BFE>if ( ({1,2,4,6,7} | std::views::filter([x](int i){ return x == i; })).size() )
BFE>  ....
BFE>


Это для того, чтобы дотнетчики приходили пальцами потыкать?
--
Re[3]: Синтаксический сахар: x in (a,b,c)
От: koenjihyakkei Россия  
Дата: 20.02.20 20:57
Оценка:
Здравствуйте, GhostCoders, Вы писали:

В С++17 со сверткой можно проще:

#include <iostream>
using namespace std;

template<typename T, typename... Args>
bool in(T value, Args... args)
{
    return ((value == args) || ...);
}

int main()
{
    if (in(5, 1, 2, 4, 6, 7))
        cout << "5 in 1, 2, 4, 6, 7" << endl;
    else
        cout << "5 not in 1, 2, 4, 6, 7" << endl;
    if (in(4, 1, 2, 4, 6, 7))
        cout << "4 in 1, 2, 4, 6, 7" << endl;        
    else
        cout << "4 not in 1, 2, 4, 6, 7" << endl;        
    return 0;
}
Re[2]: ranges ?
От: Voivoid Россия  
Дата: 21.02.20 07:00
Оценка: 12 (2)
Здравствуйте, B0FEE664, Вы писали:

BFE>Уважаемые коллеги, а кто-нибудь может показать решение этого вопроса с помощью ranges?


https://godbolt.org/z/rzD67Z

#include "range/v3/algorithm/contains.hpp"
#include <array>

int main() {
  if( ranges::contains(std::array{1,2,3,4,5,6}, 42) ) {
      return 0;
  }
  return 1;
}
Re[3]: ranges ?
От: andyp  
Дата: 21.02.20 08:59
Оценка:
Здравствуйте, Voivoid, Вы писали:

V>
V>#include "range/v3/algorithm/contains.hpp"
V>#include <array>

V>int main() {
V>  if( ranges::contains(std::array{1,2,3,4,5,6}, 42) ) {
V>      return 0;
V>  }
V>  return 1;
V>}

V>


Порадовало, что это компилятор до return 1 смог оптимизировать.
Re[4]: ranges ?
От: rg45 СССР  
Дата: 21.02.20 09:55
Оценка:
Здравствуйте, andyp, Вы писали:

A>Порадовало, что это компилятор до return 1 смог оптимизировать.


Вот так почестнее будет:

https://godbolt.org/z/irQRU9

int main() {
    int x {};
    std::cin >> x;
    if( ranges::contains(std::array{1,2,3,4,5,6}, x) ) {
        return 0;
    }
    return 1;
}



P.S. Ну и для сравнения:

https://godbolt.org/z/2nTHxD

template <typename T, typename...U>
bool in_list(T&& t, U&&...u) {
    return ((t == u) || ...);
}

int main() {
    int x {};
    std::cin >> x;
    if( in_list(x,1,2,3,4,5,6) ) {
        return 0;
    }
    return 1;
}
--
Отредактировано 21.02.2020 10:07 rg45 . Предыдущая версия .
Re[5]: ranges ?
От: andyp  
Дата: 21.02.20 10:21
Оценка: +1 :)
Здравствуйте, rg45, Вы писали:


R>P.S. Ну и для сравнения:


Тоже читерство. Циферки подряд Но, кстати, работа оптимизатора и тут впечатляет.
Re[3]: ranges ?
От: B0FEE664  
Дата: 21.02.20 12:40
Оценка:
Здравствуйте, Voivoid, Вы писали:

BFE>>Уважаемые коллеги, а кто-нибудь может показать решение этого вопроса с помощью ranges?

V>https://godbolt.org/z/rzD67Z

V>
V>#include "range/v3/algorithm/contains.hpp"
V>#include <array>

V>int main() {
V>  if( ranges::contains(std::array{1,2,3,4,5,6}, 42) ) {
V>      return 0;
V>  }
V>  return 1;
V>}

V>


Не понятно зачем нужен std::array, должно ведь и так работать: ranges::contains({1,2,3,4,5,6}, 42). Или нет?
И каждый день — без права на ошибку...
Re[4]: ranges ?
От: rg45 СССР  
Дата: 21.02.20 13:02
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Не понятно зачем нужен std::array, должно ведь и так работать: ranges::contains({1,2,3,4,5,6}, 42). Или нет?


Это зависит от того, как объявлен параметр. Если просто T&& или const T&, то не выведется.
--
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.