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

C++11 (C++0x), знаем ли мы его? Так ли он хорош? (15 стр)

Страницы: 110 11 12 13 14 15
#210
22:53, 28 дек 2011

kipar
> Т.е. в D по-твоему есть слабенький рефлекшн, я правильно понимаю?
Да, это довольно слабая рефлексия. По хорошему нужно не только иметь доступ к списку методов во времени компиляции, но и к исходному коду методов(вплоть до
комментариев), причем исходный код методов должен предоставляться в виде дерева(короче, информации должно быть достаточно, для полного восстановления исходного кода метода). такие дела.

#211
22:53, 28 дек 2011

/A\
> А мне удалось, но получилось еще страшнее.
Самое плохое, что это медленно компилируется и не может более 10 элементов массива в данном исполнении, хотя идея интересная. Я подумаю.

> Еще переделал макрос, теперь смотрится получше.
Да, вот это уже хорошо. И вопреки моим ожиданиям работает для 0 элементов. Кроме появления лишней переменной в области видимости и нестандартного синтаксиса других побочных явлений нет. Разве что ещё есть if(1)MAKE_ARRAY(, что вызовет ошибку компиляции из-за двухстрочности макроса.

Я, правда не понял, почему это работает для 0 элементов? С каких пор в С++ разрешены С-массивы 0'вой длины? Неужели С++11 стандарт их разрешил?

Доработал вариант с макросом:

template<class TItem, size_t N>
constexpr size_t count_of_for_make_array( TItem(&&x)[N] )
{
  return N;
}

#define MAKE_ARRAY( _type, _name, _args... ) \
  array< _type, count_of_for_make_array( (_type[]){ _args } ) >  _name = {{ _args }}
    
int main(void)
{
  MAKE_ARRAY( int, a, 4, 5, 6 ,7, 8);
  for(auto i : a)
    cout<<i<<' ';

Ушла болтающаяся и возможно конфликтующая лишняя переменная. Ушла двухстрочность, иногда вызывающая непонятные ошибки компиляции. Но теперь не компилируется при 0ле элементов. Старая компилировала вариант с 0м элементов. Хоть это не так сильно нужно, но есть идеи, как исправить?

Всё-таки очень хотелось бы сделать вариант с auto a=make_array(. Он даже тип указывать не требует. Это было бы самое красивое.

#212
23:18, 28 дек 2011

Да, это ещё одна странность стандарта:
C-массивы 0вой длины теперь можно объявлять, но нельзя передавать в функции.

И всеже почему для контейнера

array<int,6> a={{1,8,3,4,4,6}};

используется }} две скобки, а не одна, хотя для всех остальных контейнеров одна? В чем причина такого странного поведения?

#213
23:34, 28 дек 2011

laMer007
> В чем причина такого странного поведения?
Покажи как у тебя объявленны конструкторы для array, скорее всего там используется std'шный список инициализации.

На MVC2010 работает с одной и двумя скобками, но там конструкторы не объявлены.

#214
23:53, 28 дек 2011

laMer007
> В чем причина такого странного поведения?
У array нет конструктора, принимающего initializer_list. Но его устройство таково, что он агрегирует обычный pod массив. Поэтому {{data}} работает как для любой другой структуры, агрегирующей другие типы.

#215
0:41, 29 дек 2011

/A\
> На MVC2010 работает с одной и двумя скобками, но там конструкторы не объявлены.
Microsoft такой Microsoft... initializer_list не осилила, но std::array инициализируе... понятно.

RPGman
>У array нет конструктора, принимающего initializer_list. Но его устройство таково, что он агрегирует обычный pod массив.
Да, я это понял, пока писал предыдущее предложение, спасибо.

/A\
> На MVC2010 работает с одной и двумя скобками
А с одной скобкой { разве должен std::array работать, если конструктор от initializer_list не объявлен?

#216
1:20, 29 дек 2011

laMer007
Кстати, такое поведение array в gcc может измениться. Я не нашел требований к реализации array, а она может быть разной, и {{}} может не везде работать.
Более того, Стауструп пишет вот чего: http://www2.research.att.com/~bs/C++0xFAQ.html#std-array
Ага, нашел. Array в gcc реализован некорректно с точки зрения стандарта.

An array is an aggregate (8.5.1) that can be initialized with the syntax array<T, N> a = { initializer-list };

зы: Еще линк: http://stackoverflow.com/questions/8192185/using-stdarray-with-in… ization-lists
Т.е. реализация std::array в gcc правильная. Инициализируется array по прежнему как aggregate.
Только gcc не прав, не позволяя опускать внешние скобки, хотя стандарт допускает такой финт.
В то же время опускание некоторых скобок считается плохим тоном. Такой список хуже читается, и может давать разные результаты на разных компиляторах.

#217
22:03, 8 янв 2012

> Только gcc не прав, не позволяя опускать внешние скобки
Версия 4.7.0, снапшот от 7 января 2012, "глюк" с двойными скобками в array пофиксен :)

#218
23:24, 8 янв 2012

Adler
> Да, это довольно слабая рефлексия. По хорошему нужно не только иметь доступ к
> списку методов во времени компиляции, но и к исходному коду методов(вплоть до
> комментариев), причем исходный код методов должен предоставляться в виде
> дерева(короче, информации должно быть достаточно, для полного восстановления
> исходного кода метода). такие дела.
Ну да, авторы D упоминали что компиляция произвольных строк это все-таки костыль, и возможно в будущем будет вместо них добавлен способ работы напрямую с отпарсенным деревом.

#219
23:26, 8 янв 2012

Блин, я шляпа...
Проглядел, что это изначально был ворнинг, а не ошибка, почему и подумал про "баг".
Все нормально работало и раньше. Ворнинг показывается с опцией -Wall, просто из соображений безопасности кода. Инициализация агрегатов без вложенных скобок втихую откомпилируется и после изменения структуры агрегата, давая совершенно иной результат. Поэтому и ворнинг.
Сорри за шум...

#220
23:26, 8 янв 2012

kipar
> возможно в будущем будет вместо них добавлен способ работы напрямую с отпарсенным деревом.
Back to Lisp :)

#221
13:04, 1 фев 2012

не пропустите
http://channel9.msdn.com/Events/GoingNative/GoingNative-2012

Прошло более 10 месяцев
#222
17:12, 21 дек 2012

Помещу здесь, чтобы не потерялось:
Перегруженная лямбда:
http://liveworkspace.org/code/3E4Knc$15

#include <string>
#include <iostream>
#include <functional>
 
using namespace std;

template<class Lambda1, class Lambda2>
struct OverloadLambda: Lambda1, Lambda2{
   OverloadLambda(const Lambda1& l1, const Lambda2& l2):Lambda1(l1), Lambda2(l2){}
   using Lambda1::operator();
   using Lambda2::operator();
};

template<class Lambda1, class Lambda2>
OverloadLambda<Lambda1, Lambda2> OverloadLambdaMake(const Lambda1& l1, const Lambda2& l2){
   return OverloadLambda<Lambda1, Lambda2>(l1, l2);
}

int main() {
   int i=5;
   auto lambda=OverloadLambdaMake(  [=](int v){cout<<__func__<<" "<<i<<" "<<v<<endl;},
                                    [=](string v){cout<<__func__<<" "<<i<<" "<<v<<endl;});
   lambda(0);
   lambda("Hello");
   return 0;
}

Можно накатать перегруженную лямбду на произвольное кол-во лямбд.

#223
0:19, 22 дек 2012

Можно конечно в С++03 например через BOOST::MPL::PREPROCESSOR, но крайне не красиво, медленно и отлаживаться нельзя.
Смотрите как красиво получется в С++11:
http://liveworkspace.org/code/1Uz6ox$43

#include <string>
#include <iostream>
#include <functional>
 
using namespace std;

template<class L, class... Ls>
struct OL: L, OL<Ls...>{
   OL(const L& l, const Ls&... ls): L(l), OL<Ls...>(ls...){}
   using L::operator();
   using OL<Ls...>::operator();
};

template<class L1, class L2>
struct OL<L1, L2>: L1, L2{
   OL(const L1& l1, const L2& l2): L1(l1), L2(l2){}
   using L1::operator();
   using L2::operator();
};


template<class... Ls>
OL<Ls...> OverloadLambda(const Ls&... l){
   return OL<Ls...>(l...);
}

template<class L>
L OverloadLambda(const L& l){
   return l;
}

void OverloadLambda(void) = delete;

int main() {
   int i=5;
   auto lambda=OverloadLambda(  [=](int v){cout<<__func__<<" "<<i<<" "<<v<<" int"<<endl;},
                                [=](string v){cout<<__func__<<" "<<i<<" "<<v<<" string"<<endl;},
                                [=](float v){cout<<__func__<<" "<<i<<" "<<v<<" float"<<endl;});
   lambda(0);
   lambda("Hello");
   lambda(1.0f);
   i=600;
   auto lambda1=OverloadLambda( [=](int v){cout<<__func__<<" "<<i<<" "<<v<<" int"<<endl;});
   lambda1(4);
   ///*auto lambda0 =*/ OverloadLambda();
   return 0;
}

Неплохой манул по variadic templates.
Так что C++11 нужен.

#224
0:47, 22 дек 2012

На самом деле конечно шучу.
Нужно не мудурствуя лукаво писать например примерно так:

int main() {
int i = 5;
struct _{ const int i; _(int i):i(i){}
  void operator()(int v){cout<<__func__<<" "<<i<<" "<<v<<" int"<<endl;}
  void operator()(string v){cout<<__func__<<" "<<i<<" "<<v<<" string"<<endl;}
  void operator()(float v){cout<<__func__<<" "<<i<<" "<<v<<" float"<<endl;}
} lambda(i);
lambda(0);
lambda("Hello");
lambda(1.0f);

Работает даже до доиторической 6ки от майкрософта и кода не больше. А самое главное без неподдерживаемого кулхацкерства.

Страницы: 110 11 12 13 14 15
ПрограммированиеФорумОбщее

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