将“Args”参数从自定义模板构造函数传递到容器构造函数

问题描述 投票:0回答:1

我正在尝试将

Args
参数从模板传递到容器
deque.emplace_back()
调用

例如

class Collection
{
public:
    template <typename ...Args>
    Collection(const std::string& name, Args...  entries)
        : m_name(name)
    {
        m_entries.emplace_back(entries...);  // Here!!!! Entry<int>, Entry<double>, Entry<int, int> added to 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}
};


基本上我想要有多个“Collection”实例,具有不同的“Entry”集(不同类型,不同数字)。并希望为所有可能的组合创建通用构造函数。

emplace_back
是具有
Args
参数重载

的模板
template< class... Args >
reference emplace_back( Args&&... args );

所以我认为它可能需要一个对象列表。但这还没有编译。 有错误

/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)...); }
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Godbolt 的完整示例 https://godbolt.org/z/YoPPToEdr

我很乐意建议如何使这项工作有效。
谢谢
c++ templates variadic-templates
1个回答
0
投票

您实际上不想在这里使用

emplace_back
,因为它会呈几何级数增长,并且当您向
deque
添加元素时会导致不必要的分配。相反,您想要做的是直接初始化类成员初始值设定项列表中的
deque
,就像初始化
string
成员一样。这会给你:

template <typename ...Args>
Collection(const std::string& name, Args...  entries) : m_name(name), m_entries{args...} {}

请注意,我们在

{}
中使用
m_entries{args...}
,因为我们想要列出初始化,并使用大括号。


如果您确实需要调用函数,那么这样做的方法是

template <typename ...Args>
Collection(const std::string& name, Args...  entries)
    : m_name(name)
{
    (m_entries.emplace_back(entries), ...);
}

这称为一元折叠表达式,语法为

( expression_using_pack op ...)
(... op expression_using_pack)
,具体取决于您分别进行右折叠还是左折叠

© www.soinside.com 2019 - 2024. All rights reserved.