Probleme mit bind und member templates
-
Hiho,
folgender Code, der das Problem aufzeigt:
#include "stdafx.h"
#include <iostream> #include <conio.h> #include <memory> #include <boost/thread.hpp> // struct Teststruct { void foo() { std::cout << "foohooo" << std::endl; } }; // void funcFoo() { std::cout << "Func foohooo" << std::endl; } // class CCycleThread : boost::noncopyable { public: /******************************************************************************/ /* constructor */ /******************************************************************************/ template<typename T> CCycleThread(T& t) { m_thread.reset(new boost::thread(boost::bind(&CCycleThread::execute<T>,this,t))); } private: /******************************************************************************/ /* thread method */ /******************************************************************************/ template<typename T> void execute(T t) { for(;;) t(); } // std::unique_ptr <boost::thread> m_thread; }; int _tmain(int argc, _TCHAR* argv[]) { Teststruct testObj; // CCycleThread cycleThread(funcFoo); //compiles CCycleThread anotherCycleThread(boost::bind(&Teststruct::foo,&testObj)); //compiles not _getch(); return 0; }Das ganze führt zu einem Compilefehler im Visual Studio 2010:
d:\quellcode\boost\boost_1_48_0\boost\bind\bind.hpp(313): error C2664: 'R boost::_mfi::mf1<R,T,A1>::operator ()<CCycleThread>(const U &,A1) const': Konvertierung des Parameters 2 von 'void' in 'boost::_bi::bind_t<R,F,L>' nicht möglich
1> with
1> [
1> R=void,
1> T=CCycleThread,
1> A1=boost::_bi::bind_t<void,boost::_mfi::mf0<void,Teststruct>,boost::_bi::list1<boost::_bi::value<Teststruct *>>>,
1> U=CCycleThread *
1> ]
1> and
1> [
1> R=void,
1> F=boost::_mfi::mf0<void,Teststruct>,
1> L=boost::_bi::list1<boost::_bi::value<Teststruct *>>
1> ]
1> Ausdruck vom Typ void kann nicht in andere Typen konvertiert werden
1> d:\quellcode\boost\boost_1_48_0\boost\bind\bind_template.hpp(20): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void boost::_bi::list2<A1,A2>::operator ()<F,boost::_bi::list0>(boost::_bi::type<T>,F &,A &,int)".
1> with
1> [
1> A1=boost::_bi::value<CCycleThread *>,
1> A2=boost::_bi::bind_t<void,boost::_mfi::mf0<void,Teststruct>,boost::_bi::list1<boost::_bi::value<Teststruct *>>>,
1> F=boost::_mfi::mf1<void,CCycleThread,boost::_bi::bind_t<void,boost::_mfi::mf0<void,Teststruct>,boost::_bi::list1<boost::_bi::value<Teststruct *>>>>,
1> T=void,
1> A=boost::_bi::list0
1> ]
1> d:\quellcode\boost\boost_1_48_0\boost\bind\bind_template.hpp(18): Bei der Kompilierung der Klassen-template der void boost::_bi::bind_t<R,F,L>::operator ()(void)-Memberfunktion
1> with
1> [
1> R=void,
1> F=boost::_mfi::mf1<void,CCycleThread,boost::_bi::bind_t<void,boost::_mfi::mf0<void,Teststruct>,boost::_bi::list1<boost::_bi::value<Teststruct *>>>>,
1> L=boost::_bi::list2<boost::_bi::value<CCycleThread *>,boost::_bi::bind_t<void,boost::_mfi::mf0<void,Teststruct>,boost::_bi::list1<boost::_bi::value<Teststruct *>>>>
1> ]
1> d:\users\mschumi\desktop\test\test\test.cpp(36): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "boost::_bi::bind_t<R,F,L>".
1> with
1> [
1> R=void,
1> F=boost::_mfi::mf1<void,CCycleThread,boost::_bi::bind_t<void,boost::_mfi::mf0<void,Teststruct>,boost::_bi::list1<boost::_bi::value<Teststruct *>>>>,
1> L=boost::_bi::list2<boost::_bi::value<CCycleThread *>,boost::_bi::bind_t<void,boost::_mfi::mf0<void,Teststruct>,boost::_bi::list1<boost::_bi::value<Teststruct *>>>>
1> ]
1> d:\users\mschumi\desktop\test\test\test.cpp(62): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "CCycleThread::CCycleThread<boost::_bi::bind_t<R,F,L>>(T &)".
1> with
1> [
1> R=void,
1> F=boost::_mfi::mf0<void,Teststruct>,
1> L=boost::_bi::list1<boost::_bi::value<Teststruct *>>,
1> T=boost::_bi::bind_t<void,boost::_mfi::mf0<void,Teststruct>,boost::_bi::list1<boost::_bi::value<Teststruct *>>>
1> ]Benutze ich nun einmal boost::bind und einmal std::bind, dann kompiliert er. Habe ich da irgendwo einen Fehler, oder ist das ein Compilerproblem?
-
rvalues an T& zu binden, funktioniert nicht so gut.
-
wenn ich ein T anstatt T& mache, kompiliert es trotzdem nicht.
-
Hiho,
Wenn ich die 2. Member Template-Methode entferne und boost::function benutzt, funktioniert es. Trotzdem würde mich sehr interessieren, warum die ursprüngliche Fassung nicht geht (und mit 2 unterschiedlichen bind Typen dann doch auf einmal kompiliert)
class CCycleThread : boost::noncopyable { public: /******************************************************************************/ /* constructor */ /******************************************************************************/ template<typename T> CCycleThread(T t) : m_threadFunc(t) { m_thread.reset(new boost::thread(boost::bind(&CCycleThread::execute,this))); } private: /******************************************************************************/ /* thread method */ /******************************************************************************/ void execute() { for(;;) m_threadFunc(); } // boost::function<void ()> m_threadFunc; // std::unique_ptr <boost::thread> m_thread; };
-
So, in der boost mailing list wurde mit der Fehler erläuert: boost::bind-Objekte kann man nesten. Dabei geht die Klasse soweit, dass genestete bind-Objekte ausgewertet werden:
bind(f,_1,bind(g,_1));
D. h. das Binding von g wird ausgeführt und der Rückgabetyp wird an das äußere bind durchgeleitet. Mein Code ging aber davon aus, dass das komplette bind-Objekt durchgeleitet/kopiert wird und nicht das Ergebnis des binds, das ist in meinem obigen Fall void, daher der Compilefehler.