2016-07-04 3 views
1

В процессе обучения, как использовать повысить дух, феникс и слитые библиотеки, я наткнулся на этот минимальный пример, который не компилируется на MSVC (2015, версия 14) и повысить 1.61.0атрибут литья для увеличения :: вариант

#include <boost/spirit/include/karma.hpp> 
#include <boost/variant/variant.hpp> 

namespace ka = boost::spirit::karma; 

struct U /* a kind of union (legacy code)*/ 
    { 
     bool kind; 
     double foo; /* if kind = true */ 
     size_t bar; /* if kind = false */ 
    }; 

typedef boost::variant<double, size_t> UVariant; 

namespace boost { namespace spirit { namespace traits { 
    template<> 
    struct transform_attribute<U,UVariant,ka::domain> 
    { 
     typedef UVariant type; 
     static type pre(U & u) { 
      switch (u.kind) 
      { 
      case true: 
       return type(u.foo); 
      case false: 
       return type(u.bar); 
      } 
     } 
    }; 
}}} 

typedef std::back_insert_iterator<std::string> iterator; 

class grm: public ka::grammar<iterator, U()> 
{ 
public: 
    grm():grm::base_type(start) 
    { 
     start = ka::attr_cast<U,UVariant >(foo | bar); 
     foo = ka::double_; 
     bar = ka::uint_; 
     */ 
    } 
private: 
    ka::rule<iterator,U()> start; 
    ka::rule<iterator,double()> foo; 
    ka::rule<iterator,size_t()> bar; 
}; 

int main(int argc, char * argv[]) 
{ 
    grm g; 
    U u; 
    u.kind = true; 
    u.foo = 1.0; 

    std::string generated; 
    std::back_insert_iterator<std::string> sink(generated); 
    ka::generate(sink,g,u); 


    return 0; 
} 

Затем я получаю следующее сообщение об ошибке:

ошибка C2665: 'подталкивание :: подробнее :: вариант :: make_initializer_node :: применять :: initializer_node :: инициализации': ни один из 5 перегрузок могут конвертировать все типы аргументов

Сообщалось об аналогичной проблеме here, хотя я не мог понять, как ответ указывает на проблему, и является ли эта проблема той же проблемой, что и все типы, которые были правильно предоставлены (нет необходимости в преобразованиях типов).

ответ

1

Проблема заключается в том, что Spirit не выбирает ваш пользовательский transform_attribute пункт настройки. Он использует значение по умолчанию и пытается построить boost::variant<double,size_t> с const U (!!), и это, очевидно, не удается.

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

namespace boost { namespace spirit { namespace traits { 
    template<> 
    struct transform_attribute<const U,UVariant,ka::domain> 
           ^^^^^^^ 
    { 
     typedef UVariant type; 
     static type pre(const U & u) { 
         ^^^^^^^ 
      //same as before 
     } 
    }; 
}}} 

, а затем он будет подобран Карма и все будет работать.

Полный образец (On rextester):

#include <boost/spirit/include/karma.hpp> 
#include <boost/variant/variant.hpp> 

namespace ka = boost::spirit::karma; 

struct U /* a kind of union (legacy code)*/ 
    { 
     bool kind; 
     double foo; /* if kind = true */ 
     size_t bar; /* if kind = false */ 
    }; 

typedef boost::variant<double, size_t> UVariant; 

namespace boost { namespace spirit { namespace traits { 
    template<> 
    struct transform_attribute<const U,UVariant,ka::domain> 
    { 
     typedef UVariant type; 
     static type pre(const U & u) { 
      if(u.kind) 
      { 
       return type(u.foo); 
      } 
      else 
      { 
       return type(u.bar); 
      } 
     } 
    }; 
}}} 

typedef std::back_insert_iterator<std::string> iterator; 

class grm: public ka::grammar<iterator, U()> 
{ 
public: 
    grm():grm::base_type(start) 
    { 
     start = ka::attr_cast<UVariant>(foo | bar); 
     foo = ka::double_; 
     bar = ka::uint_; 
    } 
private: 
    ka::rule<iterator,U()> start; 
    ka::rule<iterator,double()> foo; 
    ka::rule<iterator,size_t()> bar; 
}; 

int main(int argc, char * argv[]) 
{ 
    grm g; 
    U u; 
    u.kind = false; 
    u.foo = 1.0; 
    u.bar = 34; 

    std::string generated; 
    std::back_insert_iterator<std::string> sink(generated); 
    ka::generate(sink,g,u); 

    std::cout << generated << std::endl; 


    return 0; 
} 
+0

Это делает работу, спасибо. Знаете ли вы это по опыту или тщательно изучите сообщение об ошибке x ko компилятора? – Heyji

+0

Сообщения об ошибках Клана довольно ясны, и это помогло мне. Точная ошибка: 'в создании функции-члена 'boost :: spirit :: karma :: transform_attribute , void> :: pre' запрошен здесь'. – llonesmiz

Смежные вопросы