我正在尝试创建一个接受带有特定签名的boost
仿函数的函数(为了我们的目的,我们说boost::function<int (std::vector<int>&)>
)。所述仿函数是从一个坏的图书馆收到的,该图书馆有抛弃异常的坏习惯。我有一种特殊的处理方式。让我们说将它们扔给stderr
。所以我制作了以下代码。
#include <iostream>
#include <vector>
#include <string>
#include <stdexcept>
#include <boost/function.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/exceptions.hpp>
void dispatchError (std::string str) {
std::cerr << str << std::endl;
}
typedef boost::function<int(std::vector<int>&)> IntFunctor;
IntFunctor make_safe(std::string method, IntFunctor functor) {
// Wrap the method in try-catch
return boost::lambda::try_catch(
// Create a lambda-like out of the method
boost::lambda::bind<int>(functor, boost::lambda::_1),
// Catch all exceptions thrown
boost::lambda::catch_exception<std::exception>(
boost::lambda::bind(
&dispatchError,
boost::lambda::bind(&std::exception::what, boost::lambda::_e))),
// Catch all non-exceptions thrown
boost::lambda::catch_all(
boost::lambda::bind(&dispatchError, "unknown:" + method)));
}
int unsafe_vec_manipulator(std::vector<int>& vec) {
throw std::runtime_error("Your example is too contrived.");
}
int main(int argc, char *argv[])
{
std::vector<int> vec(30, 1);
IntFunctor f_unsafe, f_safe;
f_unsafe = unsafe_vec_manipulator;
f_safe = make_safe("manipulator", f_unsafe);
return 0;
}
然而,当我尝试运行它时,我得到:
$ g++ test.cpp -o test && ./test
In file included from test.cpp:8:
/usr/local/include/boost/lambda/exceptions.hpp:186:5: error: implicit instantiation of
undefined template 'boost::STATIC_ASSERTION_FAILURE<false>'
BOOST_STATIC_ASSERT(throws_for_sure<Arg>::value);
^
/usr/local/include/boost/static_assert.hpp:154:13: note: expanded from macro
'BOOST_STATIC_ASSERT'
sizeof(::boost::STATIC_ASSERTION_FAILURE< BOOST_STATIC_ASSERT_BOOL...
^
/usr/local/include/boost/lambda/exceptions.hpp:222:19: note: in instantiation of
function template specialization
'boost::lambda::detail::return_or_throw_phase2<false>::call<int, const
boost::lambda::lambda_functor<boost::lambda::lambda_functor_base<boost::lambda::action<2,
boost::lambda::function_action<2, boost::lambda::detail::unspecified> >,
boost::tuples::tuple<void (*const)(std::__1::basic_string<char>), const
boost::lambda::lambda_functor<boost::lambda::lambda_functor_base<boost::lambda::action<2,
boost::lambda::function_action<2, boost::lambda::detail::unspecified> >,
boost::tuples::tuple<const char *(std::exception::*const)() const, const
boost::lambda::lambda_functor<boost::lambda::placeholder<EXCEPTION> >,
boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type> > >,
boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type,
boost::tuples::null_type, boost::tuples::null_type> > >, std::__1::vector<int,
std::__1::allocator<int> >, const boost::tuples::null_type, const
boost::tuples::null_type, std::exception>' requested here
>::template call<RET>(arg, CALL_ACTUAL_ARGS);
^
/usr/local/include/boost/lambda/exceptions.hpp:846:18: note: in instantiation of
function template specialization 'boost::lambda::detail::return_or_throw<int,
boost::lambda::lambda_functor<boost::lambda::lambda_functor_base<boost::lambda::action<2,
boost::lambda::function_action<2, boost::lambda::detail::unspecified> >,
boost::tuples::tuple<void (*const)(std::__1::basic_string<char>), const
boost::lambda::lambda_functor<boost::lambda::lambda_functor_base<boost::lambda::action<2,
boost::lambda::function_action<2, boost::lambda::detail::unspecified> >,
请注意,由于我遇到的提升版本,我无法使用boost phoenix。我也坚持使用C ++ 98。希望这是足够的信息。
答案 0 :(得分:1)
好的,我发现我做错了什么:忘了检查catch表达式的类型。这是一个工作版本:
#include <iostream>
#include <vector>
#include <string>
#include <stdexcept>
#include <boost/function.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/exceptions.hpp>
int dispatchError (std::string str) {
std::cerr << str << std::endl;
return -1;
}
typedef boost::function<int(std::vector<int>&)> IntFunctor;
IntFunctor make_safe(std::string method, IntFunctor functor) {
// Wrap the method in try-catch
return boost::lambda::try_catch(
// Create a lambda-like out of the method
boost::lambda::bind<int>(functor, boost::lambda::_1),
// Catch all exceptions thrown
boost::lambda::catch_exception<std::exception>(
boost::lambda::bind(
&dispatchError,
boost::lambda::bind(&std::exception::what, boost::lambda::_e))),
// Catch all non-exceptions thrown
boost::lambda::catch_all(
boost::lambda::bind(&dispatchError, "unknown:" + method)));
}
int unsafe_vec_manipulator(std::vector<int>& vec) {
throw std::runtime_error("Your example is too contrived.");
}
int main(int argc, char *argv[])
{
std::vector<int> vec(30, 1);
IntFunctor f_unsafe, f_safe;
f_unsafe = unsafe_vec_manipulator;
f_safe = make_safe("manipulator", f_unsafe);
f_safe(vec);
return 0;
}