You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现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();
};

关键修改点

  1. 修正返回类型推导:将decltype(std::invoke_result<Mapping, Types>())改为std::invoke_result_t<Mapping, Types&>,因为映射函数实际接收的是元组元素的左值引用,类型推导必须匹配实际参数类型。
  2. 保留lambda原始类型:将details::perform_mapping返回类型中的std::decay_t<Mapping>改为Mapping,避免带this捕获的lambda类型被不必要的衰减,导致类型信息丢失。
  3. 移除冗余头文件:删除重复导入的<string>头文件。

修改后代码可正常编译运行,perform_mapping会将std::tuple<A, B>的每个元素通过lambda调用f函数,提取出成员x的值,最终返回std::tuple<double, std::string>类型的结果。

内容的提问来源于stack exchange,提问作者SpeakX

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 03:19:57