c++ std::apply emplace_back with a parameter pack

pdkcd3nj  于 9个月前  发布在  其他
关注(0)|答案(1)|浏览(77)

我试图将一个新对象放置到模板函数中的容器中。由于模板函数接收到一个std::tuple,其中包含创建对象所需的参数,因此我使用std::apply和fold表达式来解包元组值。然而,它无法编译
我的代码相当于

#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,我不明白。代码有什么问题?

py49o6xq

py49o6xq1#

你的语法有点不对。

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

字符串
您正在data包上使用逗号运算符的折叠表达式,因此它扩展为

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


因为它是逗号操作符,所以只有dataN从内括号中返回,在本例中,内括号是元组的bool对象。

ss.emplace_back(data...)


扩张至

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


这就是对emplace_back的调用的样子。

相关问题