我有一个静态方法ToString(T)
和一个重载ToString(vector<T>)
。这适用于正常使用,但不适用于boost绑定。请参阅我的示例代码:
#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
答案 0 :(得分:3)
将ToString
变为仿函数并为您的向量重载operator()
。然后你可以通过bind(ToString(), ....)
将其传递给绑定,并且一切都会很好(如果你传递了仿函数,bind可以在内部解析模板,但如果只是一个函数指针则不能解析)。
像这样:
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();
}
};
答案 1 :(得分:2)
&ToString<int>
含糊不清。您应该通过将其强制转换为所需特定函数的签名来明确解决它。请参阅此相关问题:C++ - statement cannot resolve address for overloaded function
答案 2 :(得分:1)
问题在于,当您在第二种情况下使用ToString
的地址时,编译器仍然认为您的意思是第一个版本(int
)而不是vector
版本。然后当bind尝试检查参数/返回类型匹配时,它不同意。
您是否可以使用其他功能名称来消除歧义?您始终可以创建一个内联包装器ToString(vector)
,它可以调用不同名称的帮助程序,以便在您明确调用它时使用(而不是使用绑定)。
您还可以将ToString
函数地址转换为正确的重载(如另一个答案中所示),但这可能是也可能不是更清晰的解决方案。
答案 3 :(得分:0)
有了这个:
foo = boost::bind(&ToString<int>, boost::bind(&MetaData::getIntVector, this));
你明确地告诉编译器使用<int>
版本的ToString
,即使你试图传递一个向量。试试这个:
foo = boost::bind(&ToString<std::vector<int> >, boost::bind(&MetaData::getIntVector, this));
答案 4 :(得分:0)
Boost bind在函数重载方面存在一些问题。 你当然可以通过函数指针绕过这个问题。
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,你应该考虑改变函数名。