std::使用参数包应用 emplace_back

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

我正在尝试将一个新对象放入模板函数内的容器中。由于模板函数接收 std::tuple 以及创建对象所需的参数,因此我使用 std::apply 和折叠表达式来解压元组值。但是,它无法编译

我的代码相当于

#include <vector>

struct S
{
    S(float restAngle, bool useIt) 
      : restAngle(restAngle)
      , useIt(useIt)
    {}
    float restAngle;
    bool useIt;
};


int main()
{
    std::tuple t(0.0F, false);
    std::vector<S> ss;
    std::apply([&ss](auto ...data) {ss.emplace_back((data,...));}, t);
}

在 gcc 13 中失败并出现以下编译错误

n file included from /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/x86_64-linux-gnu/bits/c++allocator.h:33,
                 from /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/allocator.h:46,
                 from /opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/vector:63,
                 from <source>:1:
/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 = S; _Args = {bool&}; _Tp = S]':
/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 = S; _Args = {bool&}; _Tp = S; allocator_type = std::allocator<S>]'
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/vector.tcc:117:30:   required from 'std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {bool&}; _Tp = S; _Alloc = std::allocator<S>; reference = S&]'
<source>:18:52:   required from 'main()::<lambda(auto:1 ...)> [with auto:1 = {float, bool}]'
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/type_traits:2558:26:   required by substitution of 'template<class _Fn, class ... _Args> static std::__result_of_success<decltype (declval<_Fn>()((declval<_Args>)()...)), std::__invoke_other> std::__result_of_other_impl::_S_test(int) [with _Fn = main()::<lambda(auto:1 ...)>; _Args = {float&, bool&}]'
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/type_traits:2569:55:   [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/type_traits:161:35:   recursively required by substitution of 'template<class _Result, class _Ret> struct std::__is_invocable_impl<_Result, _Ret, true, std::__void_t<typename _CTp::type> > [with _Result = std::__invoke_result<main()::<lambda(auto:1 ...)>, float&, bool&>; _Ret = void]'
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/type_traits:161:35:   required by substitution of 'template<class ... _Bn> std::__detail::__first_t<std::integral_constant<bool, true>, typename std::enable_if<(bool)(_Bn::value), void>::type ...> std::__detail::__and_fn(int) [with _Bn = {std::__is_invocable_impl<std::__invoke_result<main()::<lambda(auto:1 ...)>, float&, bool&>, void, true, void>, std::__call_is_nothrow<std::__invoke_result<main()::<lambda(auto:1 ...)>, float&, bool&>, main()::<lambda(auto:1 ...)>, float&, bool&>}]'
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/type_traits:177:42:   required from 'struct std::__and_<std::__is_invocable_impl<std::__invoke_result<main()::<lambda(auto:1 ...)>, float&, bool&>, void, true, void>, std::__call_is_nothrow<std::__invoke_result<main()::<lambda(auto:1 ...)>, float&, bool&>, main()::<lambda(auto:1 ...)>, float&, bool&> >'
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/type_traits:3103:12:   required from 'struct std::is_nothrow_invocable<main()::<lambda(auto:1 ...)>, float&, bool&>'
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/tuple:2272:31:   required from 'constexpr const bool std::__unpack_std_tuple<template<class _Fn, class ... _ArgTypes> struct std::is_nothrow_invocable, main()::<lambda(auto:1 ...)>, std::tuple<float, bool>&>'
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/tuple:2295:14:   required from 'constexpr decltype(auto) std::apply(_Fn&&, _Tuple&&) [with _Fn = main()::<lambda(auto:1 ...)>; _Tuple = tuple<float, bool>&]'
<source>:18:15:   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 'S::S(bool&)'
  187 |         { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:5:5: note: candidate: 'S::S(float, bool)'
    5 |     S(float restAngle, bool useIt)
      |     ^
<source>:5:5: note:   candidate expects 2 arguments, 1 provided
<source>:3:8: note: candidate: 'constexpr S::S(const S&)'
    3 | struct S
      |        ^
<source>:3:8: note:   no known conversion for argument 1 from 'bool' to 'const S&'
<source>:3:8: note: candidate: 'constexpr S::S(S&&)'
<source>:3:8: note:   no known conversion for argument 1 from 'bool' to 'S&&'

我找不到代码有什么问题。显然是试图仅使用

bool
参数来调用 emplace_back,我不明白。代码有什么问题吗?

c++ c++17 fold-expression
1个回答
0
投票

你的语法有点不对劲。在

ss.emplace_back((data,...))

您在数据包上使用逗号运算符的折叠表达式,因此它扩展到

ss.emplace_back((data1, data2, ..., dataN))

并且由于它是逗号运算符,因此仅从内括号返回

dataN
,在您的情况下,它是元组的 bool 对象。要通过致电
emplace_back
获取所有包,您只需要

ss.emplace_back(data...)

扩展到

ss.emplace_back(data1, data2, ..., dataN)

这就是对

emplace_back
的调用应该是什么样的。

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