2011-05-06 8 views
1

정적 메서드 ToString(T)과 과부하 ToString(vector<T>)이 있습니다. 이것은 정상적으로 사용되지만 부스트 바인딩에서는 작동하지 않습니다. 예제 코드보기 :T 및 벡터 오버로드 <T>

#include <boost/bind.hpp> 
#include <boost/function.hpp> 
#include <boost/lexical_cast.hpp> 
#include <iostream> 
#include <sstream> 
#include <vector> 

class MetaData 
{ 
public: 
    template<typename T> 
    static std::string ToString(T inValue) 
    { 
     return boost::lexical_cast<std::string>(inValue); 
    } 

    template<typename T> 
    static std::string ToString(const std::vector<T> & inValues) 
    { 
     std::stringstream ss; 
     for (typename std::vector<T>::size_type idx = 0; idx < inValues.size(); ++idx) 
     { 
      if (idx != 0) 
      { 
       ss << ", "; 
      } 
      ss << inValues[idx]; 
     } 
     return ss.str(); 
    } 

    int getInt() { return 42; } 

    std::vector<int> getIntVector() 
    { 
     std::vector<int> result; 
     result.push_back(1); 
     result.push_back(2); 
     result.push_back(3); 
     return result; 
    } 

    void test(); 
}; 

void MetaData::test() 
{ 
    boost::function< std::string() > foo; 

    // Ok 
    foo = boost::bind(&ToString<int>, boost::bind(&MetaData::getInt, this)); 
    std::cout << foo() << std::endl; 

    // Compiler errors 
    foo = boost::bind(&ToString<int>, boost::bind(&MetaData::getIntVector, this)); 
    std::cout << foo() << std::endl; 

    // Ok 
    std::cout << ToString<int>(getIntVector()) << std::endl; 
} 

int main() 
{ 
    MetaData metaData; 
    metaData.test(); 
} 

내가 잘못하고있는 것을 아는 사람이 있습니까?

편집
이 내가지고있어 컴파일러 오류는 다음과 같습니다

/usr/include/boost/bind/bind.hpp: In member function ‘R boost::_bi::list1<A1>::operator()(boost::_bi::type<R>, F&, A&, long int) [with R = std::basic_string<char>, F = std::basic_string<char> (*)(int), A = boost::_bi::list0, A1 = boost::_bi::bind_t<std::vector<int>, boost::_mfi::mf0<std::vector<int>, MetaData>, boost::_bi::list1<boost::_bi::value<MetaData*> > >]’: 
/usr/include/boost/bind/bind_template.hpp:20:59: instantiated from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()() [with R = std::basic_string<char>, F = std::basic_string<char> (*)(int), L = boost::_bi::list1<boost::_bi::bind_t<std::vector<int>, boost::_mfi::mf0<std::vector<int>, MetaData>, boost::_bi::list1<boost::_bi::value<MetaData*> > > >, boost::_bi::bind_t<R, F, L>::result_type = std::basic_string<char>]’ 
/usr/include/boost/function/function_template.hpp:132:42: instantiated from ‘static R boost::detail::function::function_obj_invoker0<FunctionObj, R>::invoke(boost::detail::function::function_buffer&) [with FunctionObj = boost::_bi::bind_t<std::basic_string<char>, std::basic_string<char> (*)(int), boost::_bi::list1<boost::_bi::bind_t<std::vector<int>, boost::_mfi::mf0<std::vector<int>, MetaData>, boost::_bi::list1<boost::_bi::value<MetaData*> > > > >, R = std::basic_string<char>]’ 
/usr/include/boost/function/function_template.hpp:913:60: instantiated from ‘void boost::function0<R>::assign_to(Functor) [with Functor = boost::_bi::bind_t<std::basic_string<char>, std::basic_string<char> (*)(int), boost::_bi::list1<boost::_bi::bind_t<std::vector<int>, boost::_mfi::mf0<std::vector<int>, MetaData>, boost::_bi::list1<boost::_bi::value<MetaData*> > > > >, R = std::basic_string<char>]’ 
/usr/include/boost/function/function_template.hpp:722:7: instantiated from ‘boost::function0<R>::function0(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::_bi::bind_t<std::basic_string<char>, std::basic_string<char> (*)(int), boost::_bi::list1<boost::_bi::bind_t<std::vector<int>, boost::_mfi::mf0<std::vector<int>, MetaData>, boost::_bi::list1<boost::_bi::value<MetaData*> > > > >, R = std::basic_string<char>, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’ 
/usr/include/boost/function/function_template.hpp:1064:16: instantiated from ‘boost::function<R()>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::_bi::bind_t<std::basic_string<char>, std::basic_string<char> (*)(int), boost::_bi::list1<boost::_bi::bind_t<std::vector<int>, boost::_mfi::mf0<std::vector<int>, MetaData>, boost::_bi::list1<boost::_bi::value<MetaData*> > > > >, R = std::basic_string<char>, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’ 
/usr/include/boost/function/function_template.hpp:1105:5: instantiated from ‘typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, boost::function<R()>&>::type boost::function<R()>::operator=(Functor) [with Functor = boost::_bi::bind_t<std::basic_string<char>, std::basic_string<char> (*)(int), boost::_bi::list1<boost::_bi::bind_t<std::vector<int>, boost::_mfi::mf0<std::vector<int>, MetaData>, boost::_bi::list1<boost::_bi::value<MetaData*> > > > >, R = std::basic_string<char>, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, boost::function<R()>&>::type = boost::function<std::basic_string<char>()>&]’ 
main.cpp:55:81: instantiated from here 
/usr/include/boost/bind/bind.hpp:243:60: error: cannot convert ‘boost::_bi::result_traits<std::vector<int>, boost::_mfi::mf0<std::vector<int>, MetaData> >::type’ to ‘int’ in argument passing 
make: *** [all] Error 1 

답변

1

문제는 두 번째 경우에 ToString의 주소를 찍을 때, 컴파일러는 여전히 첫 번째 의미 생각이다 버전 int) 대신 vector 버전을 사용하십시오. 그런 다음 바인드가 매개 변수/반환 유형 일치를 검사하려고하면 일치하지 않습니다.

모호성을 제거하기 위해 다른 함수 이름을 사용할 수 있습니까? 바인딩이 아닌 명시 적으로 호출 할 때 사용할 다른 이름의 도우미를 호출하는 인라인 래퍼 ToString(vector)을 항상 만들 수 있습니다.

ToString 함수 주소를 올바른 오버로드로 캐스팅 할 수도 있지만 (다른 답변에서와 같이) 더 명확한 해결책 일 수도 있고 그렇지 않을 수도 있습니다.

3

ToString을 Functor로 바꾸고 벡터에 대해 operator()을 오버로드하십시오. 그럼 당신은 그냥 bind(ToString(), ....)을 통해 바인드하기 위해 전달할 수 있습니다. 그리고 모든 것이 잘 될 것입니다 (바인더는 함수를 전달할 경우 템플릿을 내부적으로 해결할 수 있지만 함수 포인터 만 사용하는 경우는 그렇지 않습니다). 이처럼

: 명시 적으로 컴파일러를 말하는거야

foo = boost::bind(&ToString<int>, boost::bind(&MetaData::getIntVector, this)); 

당신이 그것을 벡터를 전달하려는에도 불구하고, ToString<int> 버전을 사용하려면이와

struct ToString 
{ 
    template<typename T> 
    std::string operator()(T inValue) const 
    { 
     return boost::lexical_cast<std::string>(inValue); 
    } 

    template<typename T> 
    std::string operator()(const std::vector<T> & inValues) const 
    { 
     std::stringstream ss; 
     for (typename std::vector<T>::size_type idx = 0; idx < inValues.size(); ++idx) 
     { 
      if (idx != 0) 
      { 
       ss << ", "; 
      } 
      ss << inValues[idx]; 
     } 
     return ss.str(); 
    } 
}; 
0

. 이것을 시도하십시오 :

foo = boost::bind(&ToString<std::vector<int> >, boost::bind(&MetaData::getIntVector, this)); 
+0

두 경우 모두 T가 int이므로 두 경우 모두 "ToString "을 사용해야합니다. – StackedCrooked

0

부스트 바인드에는 함수 오버로딩과 관련된 몇 가지 문제점이 있습니다. 물론 함수 포인터로 문제를 우회 할 수도 있습니다.

void MetaData::test() 
{ 
    boost::function< std::string() > foo; 

    typedef std::string (*PFNToString)(int i); 
    typedef std::string (*PFNToString2)(std::vector<int> const& vec); 
    PFNToString pfn = &MetaData::ToString<int>; 
    PFNToString2 pfn2 = &MetaData::ToString<int>; 

    // Ok 
    foo = boost::bind(pfn, boost::bind(&MetaData::getInt, this)); 
    std::cout << foo() << std::endl; 

    // Compiler errors 
    foo = boost::bind(pfn2, boost::bind(&MetaData::getIntVector, this)); 
    std::cout << foo() << std::endl; 

    // Ok 
    std::cout << ToString<int>(getIntVector()) << std::endl; 
} 

하지만 bind를 사용하고 싶으므로 기능 이름을 변경하는 것이 좋습니다.