Форум программистов, компьютерный форум CyberForum.ru

binder3 - C++

Восстановить пароль Регистрация
 
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
16.07.2013, 20:35     binder3 #1
Здорова!
Есть задачка: "Напишите связывающий адаптер binder3(), который должен связывать второй и третий аргументы трехаргументной функции для получения унарного предиката. Приведите пример полезного применения binder3()."

Ни как не пойму как вернуть из функции указатель на функцию. binder3 как я понимаю должна вернуть указатель на функцию. Как мне определение написать binder3 ???
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
using std::cout;
using std::endl;
#include <algorithm>
using std::find_if;
 
bool(*)(int a) binder3(bool(*ptr)(int c,int d),int a, int b)
{
    return ptr(a, b);
}
 
//бинарный предикат
bool fun(int a,int b){return (a<b);}
 
//унарный предикат
bool fun(int a){return (a<5);}
 
int main()
{
    int mass[]={1,2,3,4,5,6};
    int* p=find_if(mass,mass+6,fun);
    cout <<*p<<endl;
 
    return 0;
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ViktorKozlov
133 / 125 / 2
Регистрация: 13.12.2012
Сообщений: 293
16.07.2013, 21:41     binder3 #2
Указатель на функцию, которая принимает 2 int'а и возвращает bool, вот так
C++
1
2
3
4
bool (*binder3(bool(*ptr)(int c,int d),int a, int b))(int,int)
{
    return ptr;
}
А вообще, лучше использовать typedef
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
16.07.2013, 21:51     binder3 #3
a) binder это не функция, это адаптер. Для "Гуру С++" поясняю - в общем случае это класс с перегруженным оператором ().
б) он не должен ничего возвращать.

Посмотри на реализацию чего-нибудь типа binder2nd. А, если говорить о функции, то посмотри bind2nd.
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
16.07.2013, 23:16  [ТС]     binder3 #4
Kastaneda, мне нужно сделать что бы так было есть допустим функция bool f(int a,int b){return (a<b);} и когда я ее передаю в binded3(f,6,7), то она б наверно делала из этой функции одноаргументную bool f(int a){return (a<7);}
Ну что то вроде binder2nd токо третий аргумент можно куда то прилепить можно такую функцию вернуть bool f(int a){return (a*6<7);} что нибудь придумать. Как это токо сделать?????

Добавлено через 1 минуту
Ладно есть идея как это сделать. Щас попробую мб получится.

Добавлено через 16 минут
Ничо не работает, ладно нужно сделать такую же фигню как binder2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
using std::cout;
using std::endl;
#include <algorithm>
using std::find_if;
 
bool binder3(bool(*ptr)(int,int),int a, int b)
{
    return ptr(1,3);
}
 
//бинарный предикат
bool fun(int a,int b){return (a>b);}
 
//унарный предикат
bool fun1(int a){return (a>3);}
 
int main()
{
    int mass[]={1,2,3,4,5,6};
    int* p=find_if(mass,mass+6,binder3(fun,1,3));
    cout <<*p<<endl;
 
    return 0;
}
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
16.07.2013, 23:45     binder3 #5
Цитата Сообщение от ninja2 Посмотреть сообщение
Ничо не работает, ладно нужно сделать такую же фигню как binder2
ну так не тупи, тебе ж сказали:
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
17.07.2013, 00:00  [ТС]     binder3 #6
Цитата Сообщение от Jupiter Посмотреть сообщение
ну так не тупи, тебе ж сказали:
Да посмотрел, там просто оказывается инициализируешь объект, передаешь в алгоритм, в объекте operator перегружен который принимает один аргумент, и вызывает сохраненную функцию с двумя параметрами.

Оказалось вроде просто, а от смогу ли я шаблон написать щас попробую.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
17.07.2013, 00:04     binder3 #7
стандартные биндеры старого стандарта достаточно уродские.
если цель - не написать велосипед, то:
в новом стандарте есть лябмды и std::bind
если все в пределах старого стандарта, то тут или написать предикат (класс с operator ()) и правильно его сконструировать или boost::bind.
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
17.07.2013, 00:06  [ТС]     binder3 #8
От красота правдаж???
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
using std::cout;
using std::endl;
#include <algorithm>
using std::find_if;
 
class binder3
{
    bool(*ptr)(int,int);
    int val;
public:
    binder3(bool(*ptr1)(int,int),int a):ptr(ptr1),val(a){}
    bool operator()(int i)
    {
        return ptr(i,val);
    }
};
 
//бинарный предикат
bool fun(int a,int b){return (a>b);}
 
//унарный предикат
bool fun1(int a){return (a>3);}
 
int main()
{
    int mass[]={1,2,3,4,5,6};
    int* p=find_if(mass,mass+6,binder3(fun,3));
    cout <<*p<<endl;
 
    return 0;
}
Добавлено через 2 минуты
DU, Да правильно угадал .
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
17.07.2013, 00:10     binder3 #9
шаблон таки ниасилил...это ж так тяжко
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
17.07.2013, 00:13  [ТС]     binder3 #10
Цитата Сообщение от Jupiter Посмотреть сообщение
шаблон таки ниасилил...это ж так тяжко
Да осилил от красавчик:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
using std::cout;
using std::endl;
#include <algorithm>
using std::find_if;
 
template<class T,class C>
class binder3
{
    C(*ptr)(T,T);
    T val;
public:
    binder3(C(*ptr1)(T,T),T a):ptr(ptr1),val(a){}
    bool operator()(T i)
    {
        return ptr(i,val);
    }
};
 
//бинарный предикат
bool fun(int a,int b){return (a>b);}
 
//унарный предикат
bool fun1(int a){return (a>3);}
 
int main()
{
    int mass[]={1,2,3,4,5,6};
    int* p=find_if(mass,mass+6,binder3<int,bool>(fun,3));
    cout <<*p<<endl;
 
    return 0;
}
Еще бы один конструктор преобразования добавить для функциональных объектов и аналог бинд2 готов.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
17.07.2013, 00:15     binder3 #11
Цитата Сообщение от ninja2 Посмотреть сообщение
C(*ptr)(T,T);
почему параметры имеют одинаковый тип?
почему тип результата bool ?
почему там жеско прописан указатель на функцию?
освободи свой разум, есть лямбды, есть функциональные объекты, они тоже хотят биндить свои параметры
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
17.07.2013, 00:33  [ТС]     binder3 #12
Цитата Сообщение от Jupiter Посмотреть сообщение
почему тип результата bool ?
Там забыл добавить С
Цитата Сообщение от Jupiter Посмотреть сообщение
почему параметры имеют одинаковый тип?
Потому что функция передается с двумя одинаковыми параметрами
Цитата Сообщение от Jupiter Посмотреть сообщение
есть функциональные объекты, они тоже хотят биндить свои параметры
От щас как раз пытаюсь для функциональных объектов как то перегрузить конструктор, но чото ничего не получается.

Добавлено через 10 минут
Jupiter, От для функциональных объектов все вроде работает.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
using std::cout;
using std::endl;
#include <algorithm>
using std::find_if;
 
/*template<class T,class C>
class binder3
{
    C(*ptr)(T,T);
    T val;
    //D obj;
public:
    binder3(C(*ptr1)(T,T),T a):ptr(ptr1),val(a){}
    //binder3(D pr,T a):ptr(0),val(a),obj(pr){}
    C operator()(T i)
    {
        return ptr(i,val);
    }
};*/
 
template<class T,class D,class C>
class binder3
{
    C obj;
    T val;
    //D obj;
public:
    binder3(C& obj1,T a):obj(obj1),val(a){}
    //binder3(D pr,T a):ptr(0),val(a),obj(pr){}
    D operator()(T i)
    {
        return obj(i,val);
    }
};
 
//бинарный предикат
bool fun(int a,int b){return (a>b);}
 
struct pr
{
    bool operator()(int a,int b){return (a>b);}
}pr1;
 
int main()
{
    int mass[]={1,2,3,4,5,6};
    int* p=find_if(mass,mass+6,binder3<int,bool,pr>(pr1,3));
    cout <<*p<<endl;
 
    return 0;
}
Красивые шаблоны получились?

Добавлено через 1 минуту
Да шаблоны тяжело писать.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
17.07.2013, 00:35     binder3 #13
вот мой велосипедик:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
template <typename BinPred, typename T>
class binder3 : public std::unary_function<T, bool>
{
  BinPred m_pred;
  T m_value;
 
public:
  binder3(BinPred pred, const T& value)
    : m_pred(pred)
    , m_value(value)
  {
  }
 
  result_type operator () (const argument_type& value) const
  {
    return m_pred(value, m_value);
  }
};
 
template <typename BinPred, typename T>
binder3<BinPred, T> make_binder3(BinPred pred, const T& value)
{
  return binder3<BinPred, T>(pred, value);
}
 
bool funInt(int a, int b)
{
  return a > b;
}
 
bool funLong(long a, long b)
{
  return a > b;
}
 
struct Pred
{
  bool operator () (int a, int b) const
  {
    return a > b;
  }
};
 
int main()
{
  int mass[]={1,2,3,4,5,6};
  {
    int* p=std::find_if(mass,mass + 6, make_binder3(funInt, 3));
    std::cout << *p << std::endl;
  }
 
  {
    int* p=std::find_if(mass,mass + 6, make_binder3(funLong, 3));
    std::cout << *p << std::endl;
  }
 
  {
    int* p=std::find_if(mass,mass + 6, make_binder3(Pred(), 3));
    std::cout << *p << std::endl;
  }
 
  return 0;
}
ninja2
 Аватар для ninja2
230 / 186 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
17.07.2013, 00:48  [ТС]     binder3 #14
DU, молодец шариш.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
17.07.2013, 00:50     binder3 #15
если забить на адаптируемость такого предиката, то можно пойти дальше и сделать шаблонным operator ()
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <algorithm>
#include <functional>
#include <iostream>
 
template <typename BinPred, typename T>
class binder3
{
  BinPred m_pred;
  T m_value;
 
public:
  binder3(BinPred pred, const T& value)
    : m_pred(pred)
    , m_value(value)
  {
  }
 
  template <typename U>
  bool operator () (const U& value) const
  {
    return m_pred(value, m_value);
  }
};
 
template <typename BinPred, typename T>
binder3<BinPred, T> make_binder3(BinPred pred, const T& value)
{
  return binder3<BinPred, T>(pred, value);
}
 
bool funInt(int a, int b)
{
  return a > b;
}
 
bool funLong(long a, long b)
{
  return a > b;
}
 
struct Pred
{
  bool operator () (int a, int b) const
  {
    return a > b;
  }
};
 
struct Pred2
{
  bool operator () (int a, const std::string& str) const
  {
    return a > str.length();
  }
};
 
int main()
{
  int mass[]={1,2,3,4,5,6};
  {
    int* p=std::find_if(mass,mass + 6, make_binder3(funInt, 3));
    std::cout << *p << std::endl;
  }
 
  {
    int* p=std::find_if(mass,mass + 6, make_binder3(funLong, 3));
    std::cout << *p << std::endl;
  }
 
  {
    int* p=std::find_if(mass,mass + 6, make_binder3(Pred(), 3));
    std::cout << *p << std::endl;
  }
 
  {
    const char* str = "333";
    int* p=std::find_if(mass,mass + 6, make_binder3(Pred2(), str));
    std::cout << *p << std::endl;
  }
 
  return 0;
}
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
17.07.2013, 09:35     binder3 #16
DU, ninja2, так по заданию же нужно сделать binder3 (т.е. предикат должен принимать 3 аргумента), а я у вас вижу что-то типа binder2.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
17.07.2013, 10:06     binder3 #17
С поддержкой функций обычных (чем кстати не занимется ни bind2nd, ни bind1st) будет менее симпатично.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <functional>
 
template<typename Operation>
struct binder3_t : 
   public std::unary_function<typename Operation::first_argument_type, typename Operation::result_type>
{
public:
   binder3_t(Operation op, const typename Operation::second_argument_type& s,
         const typename Operation::third_argument_type& t) :
      operation(op), second(s), third(t)
   {
   }
   typename Operation::result_type operator () (const typename Operation::first_argument_type& arg)
   {
      return operation(arg, second, third);
   }
private:
   Operation operation;
   typename Operation::second_argument_type second;
   typename Operation::third_argument_type third;
};
 
template<typename Operation, typename T1, typename T2>
binder3_t<Operation> binder3(Operation op, const T1& s, const T2& t)
{
   typename Operation::second_argument_type second(s);
   typename Operation::third_argument_type third(t);
   return binder3_t<Operation>(op, second, third);
}
 
template<typename T0, typename T1, typename T2, typename R>
struct ternary_function
{
   typedef T0 first_argument_type;
   typedef T1 second_argument_type;
   typedef T2 third_argument_type;
   typedef R result_type;
};
 
// test
 
struct multiply : ternary_function<int, int, int, int>
{
   result_type operator () (int f, int s, int t)
   {
      return f * s * t;
   }
};
 
#include <iostream>
#include <vector>
#include <algorithm>
 
int main()
{
   std::vector<int> v = {1};
   std::transform(v.begin(), v.end(), v.begin(), binder3(multiply(), 2, 3));
   std::cout << v.front() << std::endl;
}
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
17.07.2013, 10:10     binder3 #18
так по заданию же нужно сделать binder3
кстати да. я в задание даже не посмотрел. получился биндер2.
биндер 3 делается по аналогии. еще нужно от захардкоженного типа возвращаемого значения избавится, которое можно выводить либо внутри самого биндера3, либо в make функции, либо задавать явно.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
17.07.2013, 11:10     binder3 #19
DU,
еще нужно от захардкоженного типа возвращаемого значения избавится, которое можно выводить либо внутри самого биндера3, либо в make функции
А подробнее можно? Я вот что-то придумать не могу, чтобы это было хоть как-то красиво

Один из интересных вариантов - использовать boost::function_types

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <boost/function_types/result_type.hpp>
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_arity.hpp>
 
namespace desc = boost::function_types;
 
template<typename Operation>
struct binder3_t
{
   static_assert(desc::function_arity<Operation>::value == 3,
         "only ternary functions can be accepted");
   typedef typename desc::result_type<Operation>::type result_t;
   typedef typename desc::parameter_types<Operation>::type args_t;
   typedef typename boost::mpl::at_c<args_t, 0>::type first_t;
   typedef typename boost::mpl::at_c<args_t, 1>::type second_t;
   typedef typename boost::mpl::at_c<args_t, 2>::type third_t;
public:
   template<typename T1, typename T2>
   binder3_t(Operation op, const T1& s, const T2& t) :
      operation(op), second(s), third(t)
   {
   }
   result_t operator () (const first_t& arg) const
   {
      return operation(arg, second, third);
   }
private:
   Operation operation;
   second_t second;
   third_t third;
};
Но работает только с обычными функциями.
Yandex
Объявления
17.07.2013, 11:10     binder3
Ответ Создать тему
Опции темы

Текущее время: 17:42. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru