在编译下面的代码时,编译器(clang 10.0.1)在Boost的深处生成error: no type named 'type'...
。boost::adaptors::transformed
的范围库依赖关系
我应该如何改变我的模板函数result_data_type
,以避免这个编译器错误?
源代码为;
struct request_data {
std::string data;
size_t length = 0;
};
struct error {
std::string message;
};
template <typename T>
using result_value = boost::variant<T, error>;
template <typename T>
auto result_data_type(result_value<T>&& input) -> result_value<T> {
return boost::apply_visitor(
make_visitor([](const T& req) { return req; },
[](const error&) {
throw std::runtime_error("SHOULD_NEVER_HAPPEN");
return T();
}),
input);
};
BOOST_AUTO_TEST_CASE(template_test) {
using result_data = result_value<request_data>;
const auto vec_in =
std::vector<result_data>{result_data{request_data{"Hi", 2}},
result_data{request_data{"there!", 6}}};
auto vec_out =
vec | boost::adaptors::transformed(result_data_type<request_data>);
}
完整误差输出为;
[main] Building folder: aljam
[build] Starting build
[proc] Executing command: /Applications/CMake.app/Contents/bin/cmake --build /Users/alan/github/aljam/build --config Debug --target aljam -- -j 6
[build] Scanning dependencies of target aljam
[build] [ 2%] Building CXX object CMakeFiles/aljam.dir/cpp_playground/aljam.cpp.o
[build] In file included from /Users/alan/github/aljam/cpp_playground/aljam.cpp:9:
[build] In file included from /Users/alan/github/boost_1_73_0/boost/test/unit_test.hpp:18:
[build] In file included from /Users/alan/github/boost_1_73_0/boost/test/test_tools.hpp:46:
[build] In file included from /Users/alan/github/boost_1_73_0/boost/test/tools/old/impl.hpp:28:
[build] In file included from /Users/alan/github/boost_1_73_0/boost/numeric/conversion/conversion_traits.hpp:13:
[build] In file included from /Users/alan/github/boost_1_73_0/boost/numeric/conversion/detail/conversion_traits.hpp:17:
[build] In file included from /Users/alan/github/boost_1_73_0/boost/numeric/conversion/detail/meta.hpp:16:
[build] /Users/alan/github/boost_1_73_0/boost/mpl/eval_if.hpp:38:26: error: no type named 'type' in 'boost::result_of<boost::variant<aljam::request_data, aljam::error> (*const &(const boost::variant<aljam::request_data, aljam::error> &))(boost::variant<aljam::request_data, aljam::error> &&)>'
[build] typedef typename f_::type type;
[build] ~~~~~~~~~~~~~^~~~
[build] /Users/alan/github/boost_1_73_0/boost/iterator/iterator_adaptor.hpp:149:9: note: in instantiation of template class 'boost::mpl::eval_if<boost::is_same<boost::use_default, boost::use_default>, boost::result_of<boost::variant<aljam::request_data, aljam::error> (*const &(const boost::variant<aljam::request_data, aljam::error> &))(boost::variant<aljam::request_data, aljam::error> &&)>, boost::mpl::identity<boost::use_default> >' requested here
[build] : mpl::eval_if<
[build] ^
[build] /Users/alan/github/boost_1_73_0/boost/iterator/transform_iterator.hpp:48:26: note: in instantiation of template class 'boost::iterators::detail::ia_dflt_help<boost::use_default, boost::result_of<boost::variant<aljam::request_data, aljam::error> (*const &(const boost::variant<aljam::request_data, aljam::error> &))(boost::variant<aljam::request_data, aljam::error> &&)> >' requested here
[build] typedef typename ia_dflt_help<
[build] ^
[build] /Users/alan/github/boost_1_73_0/boost/iterator/transform_iterator.hpp:80:40: note: in instantiation of template class 'boost::iterators::detail::transform_iterator_base<boost::variant<aljam::request_data, aljam::error> (*)(boost::variant<aljam::request_data, aljam::error> &&), std::__1::__wrap_iter<const boost::variant<aljam::request_data, aljam::error> *>, boost::use_default, boost::use_default>' requested here
[build] : public boost::iterators::detail::transform_iterator_base<UnaryFunc, Iterator, Reference, Value>::type
[build] ^
[build] /Users/alan/github/boost_1_73_0/boost/range/adaptor/transformed.hpp:33:30: note: in instantiation of template class 'boost::iterators::transform_iterator<boost::variant<aljam::request_data, aljam::error> (*)(boost::variant<aljam::request_data, aljam::error> &&), std::__1::__wrap_iter<const boost::variant<aljam::request_data, aljam::error> *>, boost::use_default, boost::use_default>' requested here
[build] typename transform_iterator<P, It>::reference
[build] ^
[build] /Users/alan/github/boost_1_73_0/boost/range/adaptor/transformed.hpp:42:26: note: in instantiation of template class 'boost::range_detail::transform_iterator_gen<boost::variant<aljam::request_data, aljam::error> (*)(boost::variant<aljam::request_data, aljam::error> &&), std::__1::__wrap_iter<const boost::variant<aljam::request_data, aljam::error> *> >' requested here
[build] typename transform_iterator_gen<
[build] ^
[build] /Users/alan/github/aljam/cpp_playground/aljam.cpp:564:13: note: in instantiation of template class 'boost::range_detail::transformed_range<boost::variant<aljam::request_data, aljam::error> (*)(boost::variant<aljam::request_data, aljam::error> &&), const std::__1::vector<boost::variant<aljam::request_data, aljam::error>, std::__1::allocator<boost::variant<aljam::request_data, aljam::error> > > >' requested here
[build] vec | boost::adaptors::transformed(result_data_type<request_data>);
[build] ^
[build] In file included from /Users/alan/github/aljam/cpp_playground/aljam.cpp:19:
[build] In file included from /Users/alan/github/aljam/functional/range.hpp:17:
[build] /Users/alan/github/boost_1_73_0/boost/range/adaptor/transformed.hpp:57:20: error: no type named 'reference' in 'boost::iterators::transform_iterator<boost::variant<aljam::request_data, aljam::error> (*)(boost::variant<aljam::request_data, aljam::error> &&), std::__1::__wrap_iter<const boost::variant<aljam::request_data, aljam::error> *>, boost::use_default, boost::use_default>'
[build] >::reference
[build] ~~~^~~~~~~~~
[build] /Users/alan/github/aljam/cpp_playground/aljam.cpp:564:13: note: in instantiation of template class 'boost::range_detail::transformed_range<boost::variant<aljam::request_data, aljam::error> (*)(boost::variant<aljam::request_data, aljam::error> &&), const std::__1::vector<boost::variant<aljam::request_data, aljam::error>, std::__1::allocator<boost::variant<aljam::request_data, aljam::error> > > >' requested here
[build] vec | boost::adaptors::transformed(result_data_type<request_data>);
[build] ^
[build] In file included from /Users/alan/github/aljam/cpp_playground/aljam.cpp:19:
[build] In file included from /Users/alan/github/aljam/functional/range.hpp:17:
[build] /Users/alan/github/boost_1_73_0/boost/range/adaptor/transformed.hpp:96:19: error: no matching constructor for initialization of 'transformed_range<boost::variant<aljam::request_data, aljam::error> (*)(boost::variant<aljam::request_data, aljam::error> &&), const std::__1::vector<boost::variant<aljam::request_data, aljam::error>, std::__1::allocator<boost::variant<aljam::request_data, aljam::error> > > >'
[build] return transformed_range<UnaryFunction, const SinglePassRange>(
[build] ^
[build] /Users/alan/github/aljam/cpp_playground/aljam.cpp:564:13: note: in instantiation of function template specialization 'boost::range_detail::operator|<std::__1::vector<boost::variant<aljam::request_data, aljam::error>, std::__1::allocator<boost::variant<aljam::request_data, aljam::error> > >, boost::variant<aljam::request_data, aljam::error> (*)(boost::variant<aljam::request_data, aljam::error> &&)>' requested here
[build] vec | boost::adaptors::transformed(result_data_type<request_data>);
[build] ^
[build] /Users/alan/github/boost_1_73_0/boost/range/adaptor/transformed.hpp:62:13: note: candidate constructor not viable: no known conversion from 'boost::variant<aljam::request_data, aljam::error> (*const)(boost::variant<aljam::request_data, aljam::error> &&)' to 'boost::range_detail::transformed_range<boost::variant<aljam::request_data, aljam::error> (*)(boost::variant<aljam::request_data, aljam::error> &&), const std::__1::vector<boost::variant<aljam::request_data, aljam::error>, std::__1::allocator<boost::variant<aljam::request_data, aljam::error> > > >::transform_fn_type' (aka 'int') for 1st argument
[build] transformed_range(transform_fn_type f, R& r)
[build] ^
[build] /Users/alan/github/boost_1_73_0/boost/range/adaptor/transformed.hpp:40:16: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
[build] struct transformed_range :
[build] ^
[build] /Users/alan/github/boost_1_73_0/boost/range/adaptor/transformed.hpp:40:16: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
[build] 3 errors generated.
[build] make[3]: *** [CMakeFiles/aljam.dir/cpp_playground/aljam.cpp.o] Error 1
[build] make[2]: *** [CMakeFiles/aljam.dir/all] Error 2
[build] make[1]: *** [CMakeFiles/aljam.dir/rule] Error 2
[build] make: *** [aljam] Error 2
[build] Build finished with exit code 2
这似乎是一个没有帮助的错误消息,完全忽略了问题的原因。
将最后一行重写为
后auto vec_out = vec_in | boost::adaptors::transformed([](auto& result_data){ return result_data_type<request_data>(result_data); });
我收到了更有用的错误信息:
test.cc:68:118: error: cannot bind rvalue reference of type ‘result_value<request_data>&&’ {aka ‘std::variant<request_data, error>&&’} to lvalue of type ‘const std::variant<request_data, error>’
将result_data_type
更改为const result_value<T>&
而不是result_value<T>&&
修复编译错误。