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?


  • Mod

    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.


Anmelden zum Antworten