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

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

Восстановить пароль Регистрация
 
Gorillych
14 / 14 / 1
Регистрация: 04.07.2013
Сообщений: 76
04.07.2013, 23:38     Итераторы, как параметры лябда-функций в шаблонном классе #1
Доброго здоровья!

Есть такой код (упрощенный вариант для наглядного описания ситуации):
Код
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, то все норм. Подскажите, как сдесь правильно заюзать шаблоны?

Заранее спасибо.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11807 / 6786 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 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 ; 
    };
     }
};
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
04.07.2013, 23:49     Итераторы, как параметры лябда-функций в шаблонном классе #3
Gorillych, и какой по-твоему контекст ([&]) должен быть захвачен по ссылке?
ssXXss
263 / 185 / 10
Регистрация: 15.01.2011
Сообщений: 668
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);
Gorillych
14 / 14 / 1
Регистрация: 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, и какой по-твоему контекст ([&]) должен быть захвачен по ссылке?
В общем-то, никакого контекста здесь нет - хоть [&], хоть [=] - без разницы. Можно и не лямбду даже.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11807 / 6786 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 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 Посмотреть сообщение
хоть [&], хоть [=]
а можно и пустыми оставить

Gorillych
14 / 14 / 1
Регистрация: 04.07.2013
Сообщений: 76
05.07.2013, 01:08  [ТС]     Итераторы, как параметры лябда-функций в шаблонном классе #7
Croessmah, да, все заработало) Большое спасибо за помощь)
А Вы не могли бы буквально в двух словах объяснить зачем нужны были typename'ы в этих местах? Честно говоря, я еще не до конца разобрался с этими тайпнеймами )
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11807 / 6786 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 1
05.07.2013, 01:10     Итераторы, как параметры лябда-функций в шаблонном классе #8
Цитата Сообщение от Gorillych Посмотреть сообщение
А Вы не могли бы буквально в двух словах объяснить зачем нужны были typename'ы в этих местах?
чтобы указать, что iterator - это имя типа. Вообще, для типов, которые зависят от параметров шаблона лучше указывать typename, хотя в некоторых моментах компилятор сможет и сам разобраться
Gorillych
14 / 14 / 1
Регистрация: 04.07.2013
Сообщений: 76
05.07.2013, 01:12  [ТС]     Итераторы, как параметры лябда-функций в шаблонном классе #9
Цитата Сообщение от Croessmah Посмотреть сообщение
чтобы указать, что iterator - это имя типа. Вообще, для типов, которые зависят от параметров шаблона лучше указывать typename, хотя в некоторых моментах компилятор сможет и сам разобраться
Все понял) Еще раз спасибо)
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
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
и на этом понимании - в каком контексте лямбда можно мозг сломать.
это не укладывается в рамки "простого и понятного кода"
ssXXss
263 / 185 / 10
Регистрация: 15.01.2011
Сообщений: 668
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();
...
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
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*) {}
И если помнить это, то все прекрасно и понятно.
svk2140
-8 / 0 / 1
Регистрация: 04.07.2013
Сообщений: 254
05.07.2013, 14:54     Итераторы, как параметры лябда-функций в шаблонном классе #13
в следующий раз используй
C++
1
using namespace std;
не придётся каждый раз писать std::
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11807 / 6786 / 767
Регистрация: 27.09.2012
Сообщений: 16,840
Записей в блоге: 2
Завершенные тесты: 1
05.07.2013, 15:09     Итераторы, как параметры лябда-функций в шаблонном классе #14
svk2140, Этой фразой Вы подписали себе смертный приговор, сейчас налетят коршуны, в т.ч. и я

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

Да и вообще, судя по тому, что для Вас это лишь "не придется писать std", возникает вопрос - Вы вообще знаете что Вы делаете using'ом?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.07.2013, 15:13     Итераторы, как параметры лябда-функций в шаблонном классе
Еще ссылки по теме:

C++ Найти ошибки в шаблонном классе
Работа с матрицей в шаблонном классе C++
C++ Конструктор копирования в шаблонном классе

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

Или воспользуйтесь поиском по форуму:
Gorillych
14 / 14 / 1
Регистрация: 04.07.2013
Сообщений: 76
05.07.2013, 15:13  [ТС]     Итераторы, как параметры лябда-функций в шаблонном классе #15
Цитата Сообщение от svk2140 Посмотреть сообщение
в следующий раз используй
C++
1
using namespace std;
не придётся каждый раз писать std::
Спасибо за совет, не знал, что так можно делать
Yandex
Объявления
05.07.2013, 15:13     Итераторы, как параметры лябда-функций в шаблонном классе
Ответ Создать тему
Опции темы

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