От:
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;
}
От:
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() )
....
так или как-то так нельзя?
И каждый день — без права на ошибку...
От:
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)
Здравствуйте, 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;
}
Здравствуйте, 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;
}
От:
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 смог оптимизировать.
От:
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;
}
--
От:
andyp
Дата: 21.02.20 10:21
Оценка:
+1
Здравствуйте, rg45, Вы писали:
R>P.S. Ну и для сравнения:
Тоже читерство. Циферки подряд
Но, кстати, работа оптимизатора и тут впечатляет.
От:
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). Или нет?
И каждый день — без права на ошибку...
От:
rg45
Дата: 21.02.20 13:02
Оценка:
Здравствуйте, B0FEE664, Вы писали:
BFE>Не понятно зачем нужен std::array, должно ведь и так работать: ranges::contains({1,2,3,4,5,6}, 42). Или нет?
Это зависит от того, как объявлен параметр. Если просто T&& или const T&, то не выведется.
--
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить