Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/8: Рейтинг темы: голосов - 8, средняя оценка - 4.50
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
1

Итераторы, как параметры лябда-функций в шаблонном классе

04.07.2013, 23:38. Показов 1645. Ответов 14
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго здоровья!

Есть такой код (упрощенный вариант для наглядного описания ситуации):
Код
template<typename Type>
struct A
{
    std::function<Type(typename std::vector<Type>::iterator)> f1 =
    [&](typename std::vector<Type>::iterator arg)
    {
        return *arg ; 
    };
};

int main()
{
    std::vector<float> inp={1};
   
    A<float> obj;
    auto a = inp.begin();
    std::cout<<obj.f1(a);
}
Вылетает такая простыня ошибок при компиляции:
Код
g++-4.7    -c -g -std=c++11 -MMD -MP -MF build/Debug/GNU-Linux-x86/main.o.d -o build/Debug/GNU-Linux-x86/main.o main.cpp
main.cpp:38:52: ошибка: несоответствия типа/значения в аргументе 1 в списке параметров шаблона для «template<class _Signature> class std::function»
main.cpp:38:52: ошибка:   ожидался тип, обнаружено «(Type)(std::vector<_RealType>::iterator)»
main.cpp: In constructor «constexpr A<float>::A()»:
main.cpp:36:8: ошибка: invalid user-defined conversion from «<lambda(std::vector<float, std::allocator<float> >::iterator)>» to «int» [-fpermissive]
main.cpp:39:49: замечание: candidate is: <lambda(std::vector<float, std::allocator<float> >::iterator)>::operator double (*)(std::vector<float, std::allocator<float> >::iterator)() const <near match>
main.cpp:39:49: замечание:   no known conversion for implicit «this» parameter from «double (*)(std::vector<float, std::allocator<float> >::iterator) {aka double (*)(__gnu_cxx::__normal_iterator<float*, std::vector<float, std::allocator<float> > >)}» to «int»
main.cpp: В функции «int main()»:
main.cpp:53:14: замечание: synthesized method «constexpr A<float>::A()» first required here 
main.cpp:54:14: ошибка: нет декларации «inp» в этой области видимости
main.cpp:54:24: ошибка: unable to deduce «auto» from «<expression error>»
main.cpp:55:24: ошибка: «obj.A<float>::f1» нельзя использовать как функцию
Если не делать struct A шаблонной и, соответственно, заменить Type конкретно на float, то все норм. Подскажите, как сдесь правильно заюзать шаблоны?

Заранее спасибо.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.07.2013, 23:38
Ответы с готовыми решениями:

Параметры в шаблонном классе
Почему в шаблонном классе при описании функции надо два раза указывать тип параметра? В 1-ой...

Как использовать механизм сигналов и слотов в шаблонном классе?
Насколько я знаю, в qt невозможно использовать сигналы и слоты в реализации шаблонных классов, но...

Как вы шаблонном классе определить контейнер, тип которого совпадает с именем параметра шаблона?
собсно template &lt;class T&gt; class perestanovki { public: T&lt;int&gt; v; }; int main () {

Ошибки в шаблонном классе
Добрый день. Реализовал класс динамического массива. При проверке его работы столкнулся с ошибками,...

14
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
04.07.2013, 23:43 2
Вы инициализируете переменную прямо в объявлении класса.
Попробуйте так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
template<typename Type>
struct A
{
    std::function<Type(typename std::vector<Type>::iterator)> f1;
    A(){
         f1 =
    [&](typename std::vector<Type>::iterator arg)
    {
        return *arg ; 
    };
     }
};
1
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
04.07.2013, 23:49 3
Gorillych, и какой по-твоему контекст ([&]) должен быть захвачен по ссылке?
1
267 / 189 / 33
Регистрация: 15.01.2011
Сообщений: 681
05.07.2013, 00:17 4
можно еще чутка сократить :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<typename Type, typename R >
struct A
{
    std::function<R(typename Type::iterator)> f1;
    A(){
        f1 = [&]( Type::iterator arg)
        {
            return *arg ; 
        };
    }
};
//
    std::vector<float> inp (10);
    A<std::vector<float>,float> obj;
    auto a = inp.begin();
    auto d = obj.f1(a);
1
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
05.07.2013, 00:58  [ТС] 5
Croessmah, ssXXss, спасибо за ответы, Ваши варианты работают, но...
Давайте усложним задачу:

BaseClass.hpp:

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
#ifndef BASECLASS_HPP
#define BASECLASS_HPP
 
template<typename Type> 
class BaseClass
{
public:
    BaseClass(unsigned int NumelemsInVector);
    virtual void action();
    
    std::function<void(std::vector<Type>::iterator)> f;
    std::vector<Type> v;    
};
 
template<typename Type>
BaseClass<Type>::BaseClass(unsigned int NumelemsInVector) : v(NumelemsInVector)
{
    f = [&](std::vector<Type>::iterator arg){*arg += 1;};
}
 
template<typename Type>
void BaseClass<Type>::action()
{
    //Do nothing
}
 
#endif  /* BASECLASS_HPP */

DerClass.hpp:

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
#ifndef DERCLASS_HPP
#define DERCLASS_HPP
 
#include "BaseClass.hpp"
 
template<typename Type> 
class DerClass : BaseClass<Type>
{
public:
    DerClass(unsigned int NumelemsInVector);
    virtual void action() override;
};
 
template<typename Type>
DerClass<Type>::DerClass(unsigned int NumelemsInVector) : BaseClass<Type>(NumelemsInVector)
{
    
}
 
template<typename Type>
void DerClass<Type>::action()
{
    auto CurrentElement = this->v.begin(); 
    for(unsigned int i=0; i<this->v.size(); ++i)
    {
        this->f(CurrentElement);
        CurrentElement++;
    }
}
#endif  /* DERCLASS_HPP */
main.cpp:
C++
1
2
3
4
5
6
#include "DerClass.hpp"
int main()
{
   DerClass<float> obj(5);
   obj.action();
}
Теперь ошибки:
Код
In file included from DerClass.hpp:4:0,
                 from main.cpp:10:
BaseClass.hpp:11:52: ошибка: несоответствия типа/значения в аргументе 1 в списке параметров шаблона для «template<class _Signature> class std::function»
BaseClass.hpp:11:52: ошибка:   ожидался тип, обнаружено «(void)(std::vector<_RealType>::iterator)»
BaseClass.hpp: In constructor «BaseClass<Type>::BaseClass(unsigned int)»:
BaseClass.hpp:18:38: ошибка: «std::vector<_RealType, std::allocator<_Tp1> >::iterator» is not a type
BaseClass.hpp: In lambda function:
BaseClass.hpp:18:53: ошибка: invalid type argument of unary «*» (have «int»)
DerClass.hpp: In instantiation of «void DerClass<Type>::action() [with Type = float]»:
In file included from main.cpp:10:0:
main.cpp:44:16:   required from here
DerClass.hpp:26:9: ошибка: «((DerClass<float>*)this)->DerClass<float>::<anonymous>.BaseClass<float>::f» нельзя использовать как функцию
BaseClass.hpp: In instantiation of «BaseClass<Type>::BaseClass(unsigned int) [with Type = float]»:
In file included from DerClass.hpp:4:0,
                 from main.cpp:10:
DerClass.hpp:15:91:   required from «DerClass<Type>::DerClass(unsigned int) [with Type = float]»
main.cpp:43:26:   required from here
BaseClass.hpp:18:5: ошибка: invalid user-defined conversion from «BaseClass<Type>::BaseClass(unsigned int) [with Type = float]::<lambda(int)>» to «int» [-fpermissive]
BaseClass.hpp:18:50: замечание: candidate is: BaseClass<Type>::BaseClass(unsigned int) [with Type = float]::<lambda(int)>::operator void (*)(int)() const <near match>
BaseClass.hpp:18:50: замечание:   no known conversion for implicit «this» parameter from «void (*)(int)» to «int»
P.S. Сразу хочу попросить не обращать внимания на тело метода action в DerClass - это просто для наглядности написано.

Добавлено через 1 минуту
Цитата Сообщение от Jupiter Посмотреть сообщение
Gorillych, и какой по-твоему контекст ([&]) должен быть захвачен по ссылке?
В общем-то, никакого контекста здесь нет - хоть [&], хоть [=] - без разницы. Можно и не лямбду даже.
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
05.07.2013, 01:02 6
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
template<typename Type> 
class BaseClass
{
public:
    BaseClass(unsigned int NumelemsInVector);
    virtual void action();
    
    std::function<void(typename std::vector<Type>::iterator)> f;//тут typename std::vector<Type>::iterator
    std::vector<Type> v;    
};
 
template<typename Type>
BaseClass<Type>::BaseClass(unsigned int NumelemsInVector) : v(NumelemsInVector)
{
    f = [&](typename std::vector<Type>::iterator arg){*arg += 1;};//И тут typename std::vector<Type>::iterator
}
 
template<typename Type>
void BaseClass<Type>::action()
{
    //Do nothing
}
typename'ы забыли

Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от Gorillych Посмотреть сообщение
хоть [&], хоть [=]
а можно и пустыми оставить :)

1
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
05.07.2013, 01:08  [ТС] 7
Croessmah, да, все заработало) Большое спасибо за помощь)
А Вы не могли бы буквально в двух словах объяснить зачем нужны были typename'ы в этих местах? Честно говоря, я еще не до конца разобрался с этими тайпнеймами )
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
05.07.2013, 01:10 8
Цитата Сообщение от Gorillych Посмотреть сообщение
А Вы не могли бы буквально в двух словах объяснить зачем нужны были typename'ы в этих местах?
чтобы указать, что iterator - это имя типа. Вообще, для типов, которые зависят от параметров шаблона лучше указывать typename, хотя в некоторых моментах компилятор сможет и сам разобраться
1
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
05.07.2013, 01:12  [ТС] 9
Цитата Сообщение от Croessmah Посмотреть сообщение
чтобы указать, что iterator - это имя типа. Вообще, для типов, которые зависят от параметров шаблона лучше указывать typename, хотя в некоторых моментах компилятор сможет и сам разобраться
Все понял) Еще раз спасибо)
0
Каратель
Эксперт С++
6609 / 4028 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
05.07.2013, 01:27 10
IMHO
Цитата Сообщение от Gorillych Посмотреть сообщение
В общем-то, никакого контекста здесь нет
лямбда на то лябда чтобы быть в контексте...остается долько гадать что двигало разрабами нового синтаксического сахара
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct B;
 
struct A
{
    A(B*);
};
 
struct B
{
   A* a = new A(this);
};
 
A::A(B*)
{
    
}
 
int main()
{    
}
http://ideone.com/bhSrG9
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
partial class B
{
    
}
 
class A
{
   public A(B b)
   {
       
   }
}
 
partial class B
{
    A a = new A(this);
}
 
class Program
{
    static void Main()
    {
        
    }
}
http://ideone.com/g4DAUv
и на этом понимании - в каком контексте лямбда можно мозг сломать.
это не укладывается в рамки "простого и понятного кода"
0
267 / 189 / 33
Регистрация: 15.01.2011
Сообщений: 681
05.07.2013, 02:09 11
но жизнь лямбда малость упростила ) к примеру :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
int i = 900;
    int r = 555;
    int y = 800;
 
    std::thread th([&]()
    {
        int x = i + r + y;
        for(int a = 0; a < x; a++)
        {
            i += a;
        }
    });
    th.join();
...
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
05.07.2013, 14:41 12
Jupiter, Вцелом, так, да. Однако, не забываем, что инициализация в классе эквивалентна инициализации в конструкторе.

Коды по сути эквивалентны.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class B;
 
class A
{
public:
   A(B*);
};
 
class B
{
public:
   A* a = new A(this);
};
 
A::A(B*) {}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class B;
 
class A
{
public:
   A(B*);
};
 
class B
{
public:
   B() : a(new A(this))
   {
   }
   A* a;
};
 
A::A(B*) {}
И если помнить это, то все прекрасно и понятно.
1
89 / 1 / 3
Регистрация: 04.07.2013
Сообщений: 282
05.07.2013, 14:54 13
в следующий раз используй
C++
1
using namespace std;
не придётся каждый раз писать std::
0
Неэпический
17870 / 10635 / 2054
Регистрация: 27.09.2012
Сообщений: 26,737
Записей в блоге: 1
05.07.2013, 15:09 14
svk2140, Этой фразой Вы подписали себе смертный приговор, сейчас налетят коршуны, в т.ч. и я

Если Вам это так нравится, то используйте, но не навязывайте свое мнение другим, ибо для многих using namespace std; является бредом, от которого одни проблемы я в числе сторонников явного указания пространства имен!

Да и вообще, судя по тому, что для Вас это лишь "не придется писать std", возникает вопрос - Вы вообще знаете что Вы делаете using'ом?
0
15 / 15 / 3
Регистрация: 04.07.2013
Сообщений: 76
05.07.2013, 15:13  [ТС] 15
Цитата Сообщение от svk2140 Посмотреть сообщение
в следующий раз используй
C++
1
using namespace std;
не придётся каждый раз писать std::
Спасибо за совет, не знал, что так можно делать
0
05.07.2013, 15:13
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.07.2013, 15:13
Помогаю со студенческими работами здесь

String в шаблонном классе
Как сделать так, чтобы в Map&lt;int, std::string&gt; A; работало со string'ом С интами чарами и т.д. все...

Ошибка в шаблонном классе
Помогите исправить ошибку в 12 строчке: error C2248: CMyClass&lt;T&gt;::m_value: невозможно обратиться к...

Итератор в шаблонном классе
итератор в шаблонном классе?

Шаблонный друг в шаблонном классе
Добрый день! Создаю шаблонный класс, в котором перегружаю сложение: сложение какого-то нешаблонного...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru