четверг, 29 ноября 2012 г.

Boost Spirit::Qi, разбор выражений с числом элементов, большим десяти

При попытке разобрать парсером Spirit::Qi выражение, в котором более десяти элементов, компилятор сообщает об ошибках вида error: '_10' is not a member of 'qi'. Продолжительные и нерегулярные :-) раскопки исходников Qi, а так же связанных с ним Phoenix-а и fusion-а, в конце концов привели к следующим определениям, которые нужно изменить в нужную для себя сторону:
#define PHOENIX_LIMIT                   20 /* Или сколько там надо их парсить... */
#define FUSION_MAX_VECTOR_SIZE          PHOENIX_LIMIT
#define BOOST_RESULT_OF_NUM_ARGS        PHOENIX_LIMIT

После их явного задания требуемые данные успешно распарсились в вектор кортежей:
namespace ph = boost::phoenix;
namespace qi = boost::spirit::qi;
using boost::spirit::ascii::space_type;
//--------------------------------------------------------------------------
typedef double ValueType;
typedef ValueType First;        static const size_t FirstIndex = 0;
typedef ValueType Second;       static const size_t SecondIndex = FirstIndex + 1;
typedef ValueType Third;        static const size_t ThirdIndex = SecondIndex + 1;
typedef ValueType Fourth;       static const size_t FourthIndex = ThirdIndex + 1;
typedef ValueType Fifth;        static const size_t FifthIndex = FourthIndex + 1;
typedef ValueType Sixth;        static const size_t SixthIndex = FifthIndex + 1;
typedef ValueType Seventh;      static const size_t SeventhIndex = SixthIndex + 1;
typedef ValueType Eight;        static const size_t EightIndex = SeventhIndex + 1;
typedef ValueType Ninth;        static const size_t NinthIndex = EightIndex + 1;
typedef ValueType Tenth;        static const size_t TenthIndex = NinthIndex + 1;
typedef ValueType Eleventh;     static const size_t EleventhIndex = TenthIndex + 1;
typedef ValueType Twelfth;      static const size_t TwelfthIndex = EleventhIndex + 1;
typedef bool Locked;            static const size_t LockedIndex = TwelfthIndex + 1;
//--------------------------------------------------------------------------
typedef std::tuple<First,Second,Third,Fourth,Fifth,Sixth,       \
                   Seventh,Eight,Ninth,Tenth,Eleventh,Twelfth,  \
                   Locked> Data;
typedef std::vector<Data> DataContainer;
//--------------------------------------------------------------------------
struct phoenix_make_tuple_impl
{ /* Tuple create adapter  */
  template <typename... Args>
  struct result
  {
    typedef std::tuple<Args...> type;
  };
  template <typename... Args>
  typename result<Args...>::type operator () (Args... args) const
  {
    return std::make_tuple(args...);
  }
};
ph::function<phoenix_make_tuple_impl> const phoenix_make_tuple = phoenix_make_tuple_impl();
//--------------------------------------------------------------------------
template <typename Iterator,typename Container> \
struct ParserGrammar : qi::grammar              \
<Iterator,Container(),qi::blank_type>           \
{
  typedef typename Container::value_type Value;
  ParserGrammar(Container& container) :         \
    ParserGrammar::base_type(start)
  {
    start = qi::lit("Data") >> qi::lit("=") >>     \
      containerData                                \
      [ph::push_back(ph::ref(container),qi::_1)] % \
      qi::eol;
    containerData =                                     \
      (first >> second >> third >> fourth >>            \
       fifth >> sixth >> seventh >> eight >>            \
       ninth >> tenth >> eleventh >> twelfth >>         \
       locked)                                          \
      [qi::_val = phoenix_make_tuple                    \
       (qi::_1,qi::_2,qi::_3,qi::_4,qi::_5,qi::_6,      \
        qi::_7,qi::_8,qi::_9,qi::_10,qi::_11,qi::_12,   \
        qi::_13)];
    first = second = third = fourth = fifth =         \
      sixth = seventh = eight = ninth = tenth =       \
      eleventh = twelfth = qi::double_;
    locked = qi::bool_;
    return;
  }
  qi::rule<Iterator,Container(), qi::blank_type> start;
  qi::rule<Iterator,Value(), qi::blank_type> containerData;
  qi::rule<Iterator,double()>                   \
    first,second,third,fourth,fifth,sixth,      \
    seventh,eight,ninth,tenth,eleventh,twelfth;
  qi::rule<Iterator, bool()> locked;
};
//--------------------------------------------------------------------------
const std::string dataString = "Data = 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9 10.10 11.11 12.12\n\
10.10 20.20 30.30 40.40 50.50 60.60 70.70 80.80 90.90 100.100 110.110 120.120\n";


вторник, 24 июля 2012 г.

Компиляция проектов Qt версии ниже 4.8.1 с использованием MinGW GCC 4.7.0

При компиляции проектов Qt версии ниже 4.8.1 компилятором MinGW GCC 4.7.0 с использованием флага -std=c++11 некоторые макросы распознаются как пользовательские литералы, что приводит к ошибкам компиляции. Для версии Qt 4.8.1 выпущен патч, а для предыдущих версий предлагается следующий заголовочный файл, корректно (с точки зрения C++11) определяющий нужные макросы:
#ifndef CXX0XCOMPATIBILITY_HPP__20120723__1427
#define CXX0XCOMPATIBILITY_HPP__20120723__1427

/*
 * For compatibility with C++-0x mode in GCC 4.7.x
 */
//-------------------------------------------------------------------------
# ifndef QT_NO_DEBUG
#  ifdef QLOCATION
#  undef QLOCATION
#  define QLOCATION "\0" __FILE__ ":" QTOSTRING(__LINE__)
#   ifndef QT_NO_KEYWORDS
#    ifdef METHOD
#    undef METHOD
#    define METHOD(a)   qFlagLocation("0" #a QLOCATION)
#    endif
#   endif
#  endif
#  ifdef SLOT
#  undef SLOT
#  define SLOT(a)     qFlagLocation("1" #a QLOCATION)
#  endif
#  ifdef SIGNAL
#  undef SIGNAL
#  define SIGNAL(a)   qFlagLocation("2" #a QLOCATION)
#  endif
# else
#  ifndef QT_NO_KEYWORDS
#   ifdef METHOD
#   undef METHOD
#   define METHOD(a)   "0" #a
#   endif
#  endif
#  ifdef SLOT
#  undef SLOT
#  define SLOT(a)     "1" #a
#  endif
#  ifdef SIGNAL
#  undef SIGNAL
#  define SIGNAL(a)   "2" #a
#  endif
# endif

#endif//

Включение этого файла после подключенных заголовочных файлов Qt позволяет "малой кровью", без пересборки самой библиотеки Qt, решить проблему этой ошибки.

воскресенье, 26 февраля 2012 г.

Прочистка форсунок стеклоомывателя

При езде в сырую погоду часто случается досадная неприятность: грязью из-под колёс забиваются форсунки стеклоомывателя. После чего на очистку лобового (а у кого и заднего) стекла приходится тратить гораздо больше времени. Разумеется, это очень снижает безопасность вождения. При попытке прочистить каналы форсунок простой проволокой, зачастую, грязь только проталкивается дальше, к трубке подачи жидкости. В худшем случае проволока может обломиться внутри форсунки, и тогда её остаётся только заменить на новую. А до автомагазина ещё надо доехать... Решение по прочистке было найдено неожиданно, и оказалось очень эффективным. Прочищать надо такой специальной стоматологической штуковиной, под названием эндодонтический файл. Можно выпросить его (с подходящим диаметром) в стоматологическом кабинете, а можно купить в магазине, торгующем медтехникой. Цена их крайне мала -- от 10 рублей за штуку, делаются они из прочной, гибкой стали, так что сломать его внутри форсунки почти невозможно. Так же он имеет конусообразную форму, и резьбу, что позволяет вкрутить его в скопление грязи/ржавчины/чем-там-ещё-может-забиться-форсунка, и вытащить всё это богатство наружу. В общем -- рекомендую. Очень полезная штука.