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

如何从同构模板参数的完美转发函数中提取模板类型?

解决方案

你可以利用C++20的模板参数推导和完美转发特性,通过提取第一个参数的类型自动确定std::vector的元素类型,同时确保所有传入参数类型一致。以下是实现代码:

#include <vector>
#include <utility>
#include <type_traits>

template <typename T>
struct Object { T x {}; };

// 核心工厂函数实现
template <typename ObjType, typename... Args>
auto make_objects(ObjType&& first, Args&&... args) {
    // 提取第一个参数的原始类型(移除引用、const/volatile限定符)
    using ElementType = std::remove_cvref_t<ObjType>;
    
    std::vector<ElementType> vec;
    vec.reserve(1 + sizeof...(args)); // 预留空间减少扩容开销
    
    // 完美转发所有参数,用emplace_back构造元素
    vec.emplace_back(std::forward<ObjType>(first));
    (vec.emplace_back(std::forward<Args>(args)), ...);
    
    return vec;
}

// 测试代码
int main() {
    Object<int> x1 {1};
    Object<int> x2 {2};

    auto collection = make_objects(x1, x2, Object<int>(3));
    // collection 类型为 std::vector<Object<int>>,包含三个元素的副本
}

关键细节说明

  • 类型推导逻辑:通过std::remove_cvref_t<ObjType>获取第一个参数的纯类型(剥离引用、const、volatile修饰),以此作为vector的元素类型,避免显式指定模板参数。
  • 完美转发实现:使用std::forward保留每个参数的值类别(左值/右值),让emplace_back自动选择拷贝或移动构造,最大化性能。
  • 参数包展开:通过C++17引入的折叠表达式(vec.emplace_back(...), ...)遍历所有可变参数,逐个添加到vector中。
  • 隐式类型检查:如果传入不同类型的参数(比如混合Object<int>和Object<double>),编译器会在emplace_back阶段报错,因为vector只能接受同类型元素。

编译期强制类型一致(可选优化)

如果需要在编译期就明确抛出类型不匹配的错误,可以添加静态断言:

template <typename ObjType, typename... Args>
auto make_objects(ObjType&& first, Args&&... args) {
    using ElementType = std::remove_cvref_t<ObjType>;
    
    // 强制所有参数的原始类型与第一个参数一致
    static_assert((std::same_as<std::remove_cvref_t<Args>, ElementType> && ...), 
                  "All arguments must be of the same type");
    
    std::vector<ElementType> vec;
    vec.reserve(1 + sizeof...(args));
    vec.emplace_back(std::forward<ObjType>(first));
    (vec.emplace_back(std::forward<Args>(args)), ...);
    
    return vec;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 04:43:21