如何实现perform_mapping使给定C++代码正常编译运行?
问题描述
使用了一个用于元组元素映射的perform_mapping函数,但代码出现编译错误,无法正常运行。目标是让以下代码能够成功编译并执行:
#include <string> #include <tuple> #include <utility> #include <string> #include <type_traits> namespace details { template <typename Tuple, typename Mapping> struct return_type; template <template <typename ...> typename Tuple, typename ... Types, typename Mapping> struct return_type<Tuple<Types...>, Mapping> { //I changed the below line from what is in the link using type = Tuple<decltype(std::invoke_result<Mapping, Types>())...>; }; template <template <typename, std::size_t> typename Array, typename T, std::size_t Size, typename Mapping> struct return_type<Array<T, Size>, Mapping> { using type = Array<std::invoke_result_t<Mapping, T>, Size>; }; template <typename Tuple, typename Mapping> using return_type_t = typename return_type<Tuple, Mapping>::type; template <typename Tuple, typename Mapping, std::size_t ... Indices> return_type_t<std::decay_t<Tuple>, std::decay_t<Mapping>> perform_mapping(Tuple&& tup, Mapping&& mapping, std::index_sequence<Indices...>) { return {mapping(std::get<Indices>(std::forward<Tuple>(tup)))...}; } } template <typename Tuple, typename Mapping, std::size_t Size = std::tuple_size<std::decay_t<Tuple>>::value> auto perform_mapping(Tuple&& tup, Mapping&& mapping) { return details::perform_mapping(std::forward<Tuple>(tup), std::forward<Mapping>(mapping), std::make_index_sequence<Size>{}); } struct A { A(double z) : x(z){}; double x; using Type = double; }; struct B { B(std::string s) : x(std::move(s)) {} std::string x; using Type = std::string; }; struct C { C() : m_tuple({A(1.0), B("A")}) { } template<class T> typename T::Type f(T& z) { return z.x; } std::tuple<A::Type, B::Type> get() { return perform_mapping(m_tuple, [this](auto& z) { return this->f(z); }); } std::tuple<A, B> m_tuple; }; int main() { C c; auto t = c.get(); };
问题分析与修复
编译错误的核心原因是类型推导不匹配以及lambda类型处理不当,修改后可正常运行,以下是完整修复代码和关键说明:
修改后的完整代码
#include <string> #include <tuple> #include <utility> #include <type_traits> namespace details { template <typename Tuple, typename Mapping> struct return_type; template <template <typename ...> typename Tuple, typename ... Types, typename Mapping> struct return_type<Tuple<Types...>, Mapping> { // 匹配映射函数实际接收的左值引用参数,修正类型推导 using type = Tuple<std::invoke_result_t<Mapping, Types&>...>; }; template <template <typename, std::size_t> typename Array, typename T, std::size_t Size, typename Mapping> struct return_type<Array<T, Size>, Mapping> { using type = Array<std::invoke_result_t<Mapping, T&>, Size>; }; template <typename Tuple, typename Mapping> using return_type_t = typename return_type<Tuple, Mapping>::type; template <typename Tuple, typename Mapping, std::size_t ... Indices> return_type_t<std::decay_t<Tuple>, Mapping> perform_mapping(Tuple&& tup, Mapping&& mapping, std::index_sequence<Indices...>) { return {mapping(std::get<Indices>(std::forward<Tuple>(tup)))...}; } } template <typename Tuple, typename Mapping, std::size_t Size = std::tuple_size<std::decay_t<Tuple>>::value> auto perform_mapping(Tuple&& tup, Mapping&& mapping) { return details::perform_mapping( std::forward<Tuple>(tup), std::forward<Mapping>(mapping), std::make_index_sequence<Size>{} ); } struct A { A(double z) : x(z){}; double x; using Type = double; }; struct B { B(std::string s) : x(std::move(s)) {} std::string x; using Type = std::string; }; struct C { C() : m_tuple({A(1.0), B("A")}) { } template<class T> typename T::Type f(T& z) { return z.x; } std::tuple<A::Type, B::Type> get() { return perform_mapping(m_tuple, [this](auto& z) { return this->f(z); }); } std::tuple<A, B> m_tuple; }; int main() { C c; auto t = c.get(); };
关键修改点
- 修正返回类型推导:将
decltype(std::invoke_result<Mapping, Types>())改为std::invoke_result_t<Mapping, Types&>,因为映射函数实际接收的是元组元素的左值引用,类型推导必须匹配实际参数类型。 - 保留lambda原始类型:将
details::perform_mapping返回类型中的std::decay_t<Mapping>改为Mapping,避免带this捕获的lambda类型被不必要的衰减,导致类型信息丢失。 - 移除冗余头文件:删除重复导入的
<string>头文件。
修改后代码可正常编译运行,perform_mapping会将std::tuple<A, B>的每个元素通过lambda调用f函数,提取出成员x的值,最终返回std::tuple<double, std::string>类型的结果。
内容的提问来源于stack exchange,提问作者SpeakX
相关产品推荐
相关产品推荐

