std::function vs 可调用模板参数
std::function vs callable as template parameter
在下面的示例中,为什么第 20 行会导致第 27 行到第 30 行描述的错误?
在第 33 行调用 exec1
工作正常。
#include <cstdint>
#include <functional>
#include <iostream>
#include <tuple>
#include <type_traits>
template <typename... t_fields>
void exec0(std::function<std::tuple<t_fields...>()> generate,
std::function<void(t_fields &&...)> handle) {
std::tuple<t_fields...> _tuple{generate()};
std::apply(handle, std::move(_tuple));
}
template <typename t_generate, typename t_function>
void exec1(t_generate generate, t_function handle) {
auto _tuple{generate()};
std::apply(handle, std::move(_tuple));
}
int main() {
auto _h = [](uint32_t u) -> void { std::cout << "u = " << u << '\n'; };
auto _g = []() -> std::tuple<uint32_t> { return std::tuple<uint32_t>{456}; };
// exec0<uint32_t>(_g, _h);
/*
main.cpp:25:3: error: no matching function for call to 'exec0'
main.cpp:8:6: note: candidate template ignored: could not match
'function<tuple<unsigned int, type-parameter-0-0...> ()>' against '(lambda at
/var/tmp/untitled002/main.cpp:23:13)'
*/
exec1(_g, _h);
return 0;
}
g++ --version
回复:
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
即使您将 <uint32_t>
指定为模板参数,编译器似乎会尝试为参数包推导更多元素,但未能成功(因为 lambda 的类型不是 std::function<...>
), 变得心烦意乱。
您需要以某种方式禁止模板参数推导。
要么将其称为 exec0<uint32_t>({_g}, {_h});
,要么将参数类型包装在 std::type_identity_t<...>
中(或者,pre-C++20,std::enable_if_t<true, ...>
)。
然后编译器将接受您的 uint32_t
作为包中的唯一类型,并且不会尝试添加更多类型。
在下面的示例中,为什么第 20 行会导致第 27 行到第 30 行描述的错误?
在第 33 行调用 exec1
工作正常。
#include <cstdint>
#include <functional>
#include <iostream>
#include <tuple>
#include <type_traits>
template <typename... t_fields>
void exec0(std::function<std::tuple<t_fields...>()> generate,
std::function<void(t_fields &&...)> handle) {
std::tuple<t_fields...> _tuple{generate()};
std::apply(handle, std::move(_tuple));
}
template <typename t_generate, typename t_function>
void exec1(t_generate generate, t_function handle) {
auto _tuple{generate()};
std::apply(handle, std::move(_tuple));
}
int main() {
auto _h = [](uint32_t u) -> void { std::cout << "u = " << u << '\n'; };
auto _g = []() -> std::tuple<uint32_t> { return std::tuple<uint32_t>{456}; };
// exec0<uint32_t>(_g, _h);
/*
main.cpp:25:3: error: no matching function for call to 'exec0'
main.cpp:8:6: note: candidate template ignored: could not match
'function<tuple<unsigned int, type-parameter-0-0...> ()>' against '(lambda at
/var/tmp/untitled002/main.cpp:23:13)'
*/
exec1(_g, _h);
return 0;
}
g++ --version
回复:
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
即使您将 <uint32_t>
指定为模板参数,编译器似乎会尝试为参数包推导更多元素,但未能成功(因为 lambda 的类型不是 std::function<...>
), 变得心烦意乱。
您需要以某种方式禁止模板参数推导。
要么将其称为 exec0<uint32_t>({_g}, {_h});
,要么将参数类型包装在 std::type_identity_t<...>
中(或者,pre-C++20,std::enable_if_t<true, ...>
)。
然后编译器将接受您的 uint32_t
作为包中的唯一类型,并且不会尝试添加更多类型。