关于imlicit instantiation的奇怪的提升lambda异常

时间:2016-04-13 14:18:46

标签: c++ boost lambda

我正在尝试创建一个接受带有特定签名的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。希望这是足够的信息。

1 个答案:

答案 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;
}