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

如何将模板构造函数的Args参数传递给deque.emplace_back?

通用Collection构造函数编译失败的解决办法

问题背景

尝试编写通用构造函数,将模板参数Args传递给std::deque<std::any>的emplace_back(),期望创建可容纳不同类型、不同数量Entry的Collection实例,但代码编译失败。

原代码

class Collection
{
public:
    template <typename ...Args>
    Collection(const std::string& name, Args...  entries)
        : m_name(name)
    {
        m_entries.emplace_back(entries...);  // 期望将Entry<int>、Entry<double>、Entry<int, int>添加到deque
    }

private:
    std::string m_name;
    std::deque<std::any> m_entries;
};

Collection collection1
{
    "my collection",
    Entry<int>{4},
    Entry<double>{5.5},
    Entry2<int, int>{1, 2}
};

编译错误信息

/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/new_allocator.h: In instantiation of 'void std::__new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::any; _Args = {Entry<int>&, Entry<double>&, Entry2<int, int>&}; _Tp = std::any]':
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/alloc_traits.h:537:17:   required from 'static void std::allocator_traits<std::allocator<_Tp1> >::construct(allocator_type&, _Up*, _Args&& ...) [with _Up = std::any; _Args = {Entry<int>&, Entry<double>&, Entry2<int, int>&}; _Tp = std::any; allocator_type = std::allocator<std::any>]'
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/deque.tcc:170:30:   required from 'std::deque<_Tp, _Alloc>::reference std::deque<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {Entry<int>&, Entry<double>&, Entry2<int, int>&}; _Tp = std::any; _Alloc = std::allocator<std::any>; reference = std::any&]'
<source>:44:31:   required from 'Collection::Collection(const std::string&, Args ...) [with Args = {Entry<int>, Entry<double>, Entry2<int, int>}; std::string = std::__cxx11::basic_string<char>]'
<source>:58:1:   required from here
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/new_allocator.h:187:11: error: no matching function for call to 'std::any::any(Entry<int>&, Entry<double>&, Entry2<int, int>&)'
  187 |         { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

问题原因

原代码中m_entries.emplace_back(entries...)的写法错误:它试图将所有Entry类型参数一次性传递给单个std::any的构造函数,但std::any只能存储单个任意类型的值,无法同时接受多个参数构造。

解决方案

需要逐个处理每个模板参数,将每个Entry单独构造为std::any并添加到deque中。使用C++17的折叠表达式可以简洁实现这一点,同时通过std::forward实现完美转发,避免不必要的拷贝:

修正后的代码

#include <any>
#include <deque>
#include <string>
#include <utility>

// 假设Entry和Entry2的定义如下
template <typename T>
struct Entry { T value; };

template <typename T1, typename T2>
struct Entry2 { T1 a; T2 b; };

class Collection
{
public:
    template <typename ...Args>
    Collection(const std::string& name, Args&&... entries)
        : m_name(name)
    {
        // 使用折叠表达式逐个emplace_back每个Entry
        (m_entries.emplace_back(std::forward<Args>(entries)), ...);
    }

private:
    std::string m_name;
    std::deque<std::any> m_entries;
};

Collection collection1
{
    "my collection",
    Entry<int>{4},
    Entry<double>{5.5},
    Entry2<int, int>{1, 2}
};

关键说明

  1. 折叠表达式:(m_entries.emplace_back(...), ...)会展开为对每个entries参数调用一次emplace_back,例如:
    m_entries.emplace_back(std::forward<Entry<int>>(entries_1));
    m_entries.emplace_back(std::forward<Entry<double>>(entries_2));
    m_entries.emplace_back(std::forward<Entry2<int,int>>(entries_3));
    
  2. 完美转发:std::forward<Args>(entries)保留参数的左值/右值属性,避免不必要的对象拷贝,提升效率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:00:23