Войти
ПрограммированиеФорумОбщее

C++ 11, завернуть лямбду в макрос.

Страницы: 1 2 Следующая »
#0
14:06, 7 апр. 2014

Привет.
Тренирую лямбды на выдуманных велосипедах.
Хочу аналог find_if для самопального вектора, но с укороченной формой записи.

template <class Type>
class TMyVector
{
  int    ctElems;
  int    maxElems;
  Type*  pElems;

  TMyVector( int Nums )
  {  ...  }

  template<class Lamb>
  Type* _FindElem( Lamb lamb )  const
  {
    for(int i=0; i<ctElems; i++)
      if( lamb(pElems[i]) )
        return &pElems[i];

    return 0;
  }

  #define  FindElem( L )   _FindElem( [=] (decltype(Type) iter) -> bool  {  return L;  } )
};

TMyVector<VEC4> vecs(8);
vecs.PushBack( VEC4(0,0,0,0) );
vecs.PushBack( VEC4(1,0,0,0) );

VEC4* pv = vecs._FindElem( [=] ( VEC4 iter ) -> bool  {  return (iter.x==1.0f);  } );    // вот так компилится и работает

Попробовал через макрос, чтобы снаружи нужно было указать только тело лямбды:

VEC4* pv = vecs.FindElem( iter.x==1.0f );   // error C2228: left of '.x' must have class/struct/union
Почему-то не видит тип Type в макросе.


#1
14:39, 7 апр. 2014

Kroll, приведите минимальный компилирующийся код, содержащий функцию main

Телепатия:

#define  FindElem( L )   _FindElem( [=] (VEC4 iter) -> bool  {  return (L);  } )
#define  FindElem( iter )   _FindElem( [=] (decltype(Type) iter) -> bool  {  return (iter.x==1.0f);  } )
#define  FindElem( iter, expr )   _FindElem( [=] (decltype(Type) iter) -> bool  {  return (expr );  } )
#2
15:06, 7 апр. 2014
struct MyVec4
{  float x,y,z,w;

  MyVec4() {}

  MyVec4( float x_, float y_, float z_, float w_ )
  {  x = x_;
    y = y_;
    z = z_;
    w = w_;
  }
};


template <class Type>
class TMyVector
{
  int    ctElems;
  int    maxElems;
  Type*  pElems;
public:
  TMyVector( int Nums )
  {
    ctElems = 0;    maxElems = Nums;

    if( maxElems>0 )
      pElems = new Type[maxElems];
    else
      pElems = 0;
  }


  void  PushBack( const Type& Elem )
  {
    pElems[ctElems++]=Elem;
  }


  Type& operator [] (int Index)  const
  {
    return pElems[Index];
  }

  template<class Lamb>
  Type* _FindElem( Lamb lamb )  const
  {
    for(int i=0; i<ctElems; i++)
      if( lamb(pElems[i]) )
        return &pElems[i];

    return 0;
  }

  #define  FindElem( L )   _FindElem( [=] (decltype(Type) iter) -> bool  {  return L;  } )
};


int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow )
{
    TMyVector<MyVec4> vecs(8);
    vecs.PushBack( MyVec4(0,0,0,0) );
    vecs.PushBack( MyVec4(1,1,0,0) );

    MyVec4* pv1 = vecs._FindElem( [=] ( MyVec4 iter ) -> bool  {  return (iter.x==1.0f);  } );

    MyVec4* pv2 = vecs.FindElem( iter.x==1.0f );

    return 0;
}

#3
15:25, 7 апр. 2014
#define  FindElem( L )   _FindElem( [=] (decltype(Type) iter) -> bool  {  return L;  } )

Type же нет там, где ты используешь макрос

#4
15:40, 7 апр. 2014

Sergio
Да, компиль говорит, что нет. Вот думаю, как решить это. Надо как-то подставить в Type имя инстанцированного класса из шаблона.

#5
15:48, 7 апр. 2014


Kroll,
http://rextester.com/XNK67112

#6
15:52, 7 апр. 2014
vector<int> a;
std::for_each(a.begin(),a.end(),[](    
      decltype(a)::value_type    
v){});
#7
16:07, 7 апр. 2014

Kartonagnick
Вот хотел как раз без этого, указывать только тело лямбды.

А так можно и короче немного:

#define  FindElem( T, L )   _FindElem( [=] (T iter) -> bool  {  return L;  } )
...
MyVec4* pv2 = vecs.FindElem( MyVec4, iter.x==1.0f );

#8
16:13, 7 апр. 2014

Kroll
> Вот хотел как раз без этого, указывать только тело лямбды.

Никак. Компилятор не телепат.

#9
16:16, 7 апр. 2014
На что только не пойдут люди, чтобы избавиться от многословности крестов.
#10
16:35, 7 апр. 2014

laMer007
> На что только не пойдут люди, чтобы избавиться от многословности крестов.

лямбды для того и придуманы, что бы произвести функцию кратко. Заворачивать её в макрос - затея сама по себе бессмысленная. Только зазря убивает читабельность и запутывает код.
#11
19:36, 7 апр. 2014

Kroll
> #define FindElem( T, L ) _FindElem( [=] (T iter) -> bool { return L; } )
Кстати, не очень удачная идея. Зачем захват всякого хлама по значению?

Kartonagnick
Пока C++14 не примут - идея нормальная, поскольку вывода типов аргументов для лямбд нет еще. Зачем печатать лишний тип? (Ну, разве что как подсказку для IDE)

#12
19:41, 7 апр. 2014

Grey304
> Пока C++14 не примут - идея нормальная, поскольку вывода типов аргументов для
> лямбд нет еще. Зачем печатать лишний тип?

Проще по месту использования написать нормальное определение нужной лямбды.
Читать будет проще.

Модифицировать - проще.

Во всех смыслах проще.

Макрос - ботва, которая только все усложняет.

#13
21:11, 7 апр. 2014

А потом захочешь ты сделать ещё одну функцию FindElem на другом конце проекта, и приехали

#14
11:01, 8 апр. 2014

-Eugene-
Предполагается одна FindElem с разными телами лямбд. Чем это плохо? Короткая запись. Если для внешнего использования, то и документация, конечно.

Страницы: 1 2 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.