linker probleme mit boost::any
-
Ahoi...
Zur Zeit schreibe ich an einem kleinen Parser. Die Klasse token hat einen member vom Typ boost::any um den Token-Wert zum jeweiligen Typ zu speichern.
Um die Funktion des Lexers zu testen, wollte ich mir kurz ein kleines Programm schreiben, dass einen Ausdruck analysiert und die einzelnen Token ausgibt. Leider meldet beim build der Linker einige Fehler (siehe unten). Ich weiß nich woran es liegen könnte, oder wo ich den Fehler suchen muss. Das Problem enstand erst, seitdem ich boost::any verwende und meine IDE springt auch nach dem build in den boost::any header zum default ctor. Ich bin ratlos ... vlt kann mir jemand von euch weiterhelfen?!main.cpp
#include <iostream> #include <string> #include "token_type.hpp" #include "token.hpp" int main() { //bcalc::lexer lex( std::cin ); while ( std::cin.get() ) { //bcalc::token tok = lex.get_next_token(); bcalc::token tok(bcalc::tok_id, std::string("boost::any")); //bcalc::display_token(tok); //bcalc::display_token( lex.get_current_token() ); } }token_type.hpp
#ifndef _BCALC_TOKEN_TYPE_HPP__ #define _BCALC_TOKEN_TYPE_HPP__ namespace bcalc { typedef enum { // open bracket tok_ob, //closed bracked tok_cb, // literal ( true / false ) tok_lit, // identifier tok_id, // assign ( '=' ) tok_assign, // operator tok_op, // print ( <ENTER>, ';' ) tok_print, // end tok_end } token_type; } #endif // _BCALC_TOKEN_TYPE_HPP__token.hpp
#ifndef __BCALC_TOKEN_HPP__ #define __BCALC_TOKEN_HPP__ #include <iostream> #include <iomanip> #include <string> #include <boost/any.hpp> #include "token_type.hpp" namespace bcalc { class token { public: token(); explicit token( const token_type ); template<typename T> token( const token_type, const T& ); token( const token& ); inline const token_type get_type() const; template<typename T> inline T get_value() const; inline const token& set_type( const token_type ); template<typename T> inline const token& set_value( const T& ); template<typename T> inline const token& set_token( const token_type, const T& ); private: token_type m_type; boost::any m_value; }; token::token() : m_type( tok_print ) { } token::token( const token_type tt ) : m_type( tt ) { } template<typename T> token::token( const token_type tt, const T& v ) : m_type( tt ), m_value( v ) { } token::token( const token& t ) : m_type( t.m_type ), m_value( t.m_value ) { } inline const token_type token::get_type() const { return m_type; } template<typename T> inline T token::get_value() const { return boost::any_cast<T>( m_value ); } inline const token& token::set_type( const token_type tt ) { m_type = tt; return *this; } template<typename T> inline const token& token::set_value( const T& v ) { m_value = v; return *this; } template<typename T> inline const token& token::set_token( const token_type tt, const T& v ) { m_type = tt; m_value = v; return *this; } void display_token( const token& ); } #endif // __BCALC_TOKEN_HPP__obj/debug/token.o||In function `token':| /usr/include/boost/any.hpp|28|multiple definition of `bcalc::token::token()'| obj/debug/main.o:/home/mojo/projects/bcalc/test_console/token.hpp|37|first defined here| obj/debug/token.o||In function `token':| /home/mojo/projects/bcalc/test_console/token.hpp|37|multiple definition of `bcalc::token::token()'| obj/debug/main.o:/home/mojo/projects/bcalc/test_console/token.hpp|37|first defined here| obj/debug/token.o||In function `token':| /home/mojo/projects/bcalc/test_console/token.hpp|43|multiple definition of `bcalc::token::token(bcalc::token_type)'| obj/debug/main.o:/home/mojo/projects/bcalc/test_console/token.hpp|43|first defined here| obj/debug/token.o||In function `token':| /home/mojo/projects/bcalc/test_console/token.hpp|43|multiple definition of `bcalc::token::token(bcalc::token_type)'| obj/debug/main.o:/home/mojo/projects/bcalc/test_console/token.hpp|43|first defined here| obj/debug/token.o||In function `token':| /home/mojo/projects/bcalc/test_console/token.hpp|57|multiple definition of `bcalc::token::token(bcalc::token const&)'| obj/debug/main.o:/home/mojo/projects/bcalc/test_console/token.hpp|57|first defined here| obj/debug/token.o||In function `token':| /home/mojo/projects/bcalc/test_console/token.hpp|57|multiple definition of `bcalc::token::token(bcalc::token const&)'| obj/debug/main.o:/home/mojo/projects/bcalc/test_console/token.hpp|57|first defined here| ||=== Build finished: 12 errors, 0 warnings ===|
-
Mit boost::any hat der Fehler nichts zu tun, das Problem liegt ganz allein in deinem Code. Wir der Linker schon richtig sagt, sind die Konstruktoren deiner Token-Klasse mehrfach definiert. Das kommt einfach dadurch zustande, daß der Header token.hpp wohl in mehreren cpp-Dateien (die du nicht gepostet hast) inkludiert wird.
Du kannst die Konstruktoren also entweder inline machen (sind die meisten deiner anderen Funktionen in der Klasse ja auch), oder aber du lagerst sie in eine entsprechende Implementierungs-Datei (token.cpp o.ä.) aus.
-
obj/debug/token.o||In function `token':|In Ergänzung: kann es sein, dass du fälschlicherweise die token.hpp mitkompilierst?
-
Dasd schrieb:
In Ergänzung: kann es sein, dass du fälschlicherweise die token.hpp mitkompilierst?
Daran ist nichts falsch. Die .hpp wird ja per #include in die verschiedenen Übersetzungseinheiten eingebunden und jedesmal mitcompiliert. Der Fehler ist nur, dass in der .hpp keine Funktionsdefinitionen enthalten sein dürfen (außer inline deklarierte), weil sonst eben in mehreren ÜEs das entsprechende Symbol definiert ist - und das schmeckt dem Linker nicht.
-
pumuckl schrieb:
Dasd schrieb:
In Ergänzung: kann es sein, dass du fälschlicherweise die token.hpp mitkompilierst?
Daran ist nichts falsch. Die .hpp wird ja per #include in die verschiedenen Übersetzungseinheiten eingebunden und jedesmal mitcompiliert. Der Fehler ist nur, dass in der .hpp keine Funktionsdefinitionen enthalten sein dürfen (außer inline deklarierte), weil sonst eben in mehreren ÜEs das entsprechende Symbol definiert ist - und das schmeckt dem Linker nicht.
Ja, ich habe mich glaube unklar ausgedrückt. Es wirkte auf mich als hätte der OP nicht vorgehabt, die token.hpp in einer eigenen Übersetzungseinheit zu kompilieren. Ansonsten hast du natürlich vollkommen recht.