8

If I change from boost::shared_ptr to std::shared_ptr in this code snippet, I will get linker error.

#include <iostream>
#include <sstream>
#include <iterator>
#include <cctype>
#include <cmath>

#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>

#include <functional>
#include <utility>
#include <numeric>

#include <boost/assign.hpp>
#include <boost/assign/std/vector.hpp>

#include <boost/algorithm/string.hpp>

#include <boost/test/included/unit_test.hpp>
#include <boost/test/included/unit_test_framework.hpp>
#include <boost/bind.hpp>

//using namespace std;
//using namespace boost;

using std::string;
using std::ostringstream;
using namespace boost::assign;
using namespace boost::unit_test;

template<typename T> string to_string( T data ) { ostringstream ost; ost << data; return ost.str(); }

class TwoStringMasks {
public:
    string shortestCommon( string s1, string s2 ) {
        //if( s1.find( "*" ) != 0 ||
        return "";
    }
};

class two_string_masks_test {
public:
    void test_case_one() {
        string str = "TOPCODER*";
        BOOST_CHECK_EQUAL( str.find( "*" ), str.length() - 2 );
    }
};

test_suite* init_unit_test_suite( int argc, char* argv[] ) {
    boost::shared_ptr<two_string_masks_test> tester( new two_string_masks_test );
    framework::master_test_suite().add(  
        BOOST_TEST_CASE( boost::bind( &two_string_masks_test::test_case_one, tester ) ) ); 
    return 0;
}

Error:

Error   12  error C2784: 'T *boost::get_pointer(T *)' : could not deduce template argument for 'T *' from 'std::tr1::shared_ptr<_Ty>'   c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report
Error   10  error C2784: 'T *boost::get_pointer(const std::auto_ptr<_Ty> &)' : could not deduce template argument for 'const std::auto_ptr<_Ty> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report
Error   11  error C2784: 'T *boost::get_pointer(const std::auto_ptr<_Ty> &)' : could not deduce template argument for 'const std::auto_ptr<_Ty> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report
Error   8   error C2784: 'T *boost::get_pointer(const boost::shared_ptr<X> &)' : could not deduce template argument for 'const boost::shared_ptr<X> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report
Error   9   error C2784: 'T *boost::get_pointer(const boost::shared_ptr<X> &)' : could not deduce template argument for 'const boost::shared_ptr<X> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report
Error   6   error C2784: 'T *boost::get_pointer(const boost::scoped_ptr<T> &)' : could not deduce template argument for 'const boost::scoped_ptr<T> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report
Error   7   error C2784: 'T *boost::get_pointer(const boost::scoped_ptr<T> &)' : could not deduce template argument for 'const boost::scoped_ptr<T> &' from 'std::tr1::shared_ptr<_Ty>' c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report
Error   13  error C2784: 'T *boost::get_pointer(const boost::reference_wrapper<T> &)' : could not deduce template argument for 'const boost::reference_wrapper<T> &' from 'std::tr1::shared_ptr<_Ty>'   c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report
Error   14  error C2784: 'T *boost::get_pointer(const boost::reference_wrapper<T> &)' : could not deduce template argument for 'const boost::reference_wrapper<T> &' from 'std::tr1::shared_ptr<_Ty>'   c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report
Error   2   error C2784: 'optional<T>::pointer_type boost::get_pointer(boost::optional<T> &)' : could not deduce template argument for 'boost::optional<T> &' from 'std::tr1::shared_ptr<_Ty>'  c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report
Error   3   error C2784: 'optional<T>::pointer_type boost::get_pointer(boost::optional<T> &)' : could not deduce template argument for 'boost::optional<T> &' from 'std::tr1::shared_ptr<_Ty>'  c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report
Error   4   error C2784: 'optional<T>::pointer_const_type boost::get_pointer(const boost::optional<T> &)' : could not deduce template argument for 'const boost::optional<T> &' from 'std::tr1::shared_ptr<_Ty>'    c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report
Error   5   error C2784: 'optional<T>::pointer_const_type boost::get_pointer(const boost::optional<T> &)' : could not deduce template argument for 'const boost::optional<T> &' from 'std::tr1::shared_ptr<_Ty>'    c:\program files\boost\boost_1_44\boost\bind\mem_fn_template.hpp    40  1   NET Report

What did I do wrong? I guessed there was a conflict between std namespace and boost namespace, but I don't know how to fix it? Any idea?

Thanks,
Chan

roxrook
  • 13,511
  • 40
  • 107
  • 156

4 Answers4

13

It looks like you need to add an overload of get_pointer to use std::shared_ptr with boost::bind.

namespace boost { 
  template<class T> const T* get_pointer(const std::shared_ptr<T>& ptr) 
  {
    return ptr.get();
  }

  template<class T> T* get_pointer(std::shared_ptr<T>& ptr)
  {
    return ptr.get();
  }
}

I'd assume that this is already working if you use std::bind instead. Or use tester.get() in the bind.

ltjax
  • 15,837
  • 3
  • 39
  • 62
  • wow, thanks for your elegant solution. Is std::bind the same as boost::bind? – roxrook Jan 13 '11 at 16:59
  • No, it's not the same, although the interface & implementation might be identical. However, `std::bind` is conceptually derived from the boost version. It just might have been changed a little in the standardization process. – ltjax Jan 13 '11 at 17:05
6

Boost and TR1 shared pointers are separate implementations and are not compatible - pick one or the other and use it exclusively.

bdonlan
  • 224,562
  • 31
  • 268
  • 324
  • thanks, could you show me how? I want to use std::shared_ptr in this case but I could not. – roxrook Jan 13 '11 at 16:28
  • First you should probably make it clear where you're using std::tr1::shared_ptr - nothing pops out for me, but since I'm not sure which column in that error message output is supposed to be the line number it's hard to match up the errors – bdonlan Jan 13 '11 at 16:31
  • He said if he converts from boost to tr1 so presumably the one inside the bind. But as I commented he must then use tr1::bind too. My own experience is that boost is far better written than tr1 so stick with it. – CashCow Jan 13 '11 at 16:35
3

boost::bind does not know what to do with tr1::shared_ptr it knows how to handle boost::shared_ptr.

You could try tr1::bind which probably works with tr1::shared_ptr.

The only issue then is whether that will work in BOOST_TEST_CASE. If it just expects a "runnable" then a tr1::function is just as "runnable" as a boost one.

CashCow
  • 30,981
  • 5
  • 61
  • 92
  • got it fixed! Thanks a lot. Are tr1::bind & boost::bind the same? ( just different namespace )? – roxrook Jan 13 '11 at 16:38
  • No they are not the same but they both produce what is called a "runnable" which is the term for something that can act like a function, and on this occasion BOOST_TEST_CASE does not care about the implementation or the source that produced the runnable (i.e. it does not have to come from boost). – CashCow Jan 13 '11 at 17:00
1

Have you noticed that you do not explicitly include the < memory > header (nor < boost/shared_ptr.hpp > for that matter)?

If you provided some more info, it'd be easier to help.

  1. What compiler are you using?
  2. Are you expecting to use tr1 from your compiler of from boost?
  3. Do you want to access shared_ptr as std::tr1::shared_ptr or simply std::shared_ptr?
broc
  • 116
  • 1
  • 2
  • thanks for your concern. Compiler: VC++ 2010, I want std::shared_ptr since it's C++0x std, not std::tr1::shared_ptr. – roxrook Jan 13 '11 at 16:52