我需要获取涉及SFINAE的重载模板函数的地址。一个很好的例子就是在这里找到boost :: asio :: spawn ...
https://www.boost.org/doc/libs/1_70_0/doc/html/boost_asio/reference/spawn.html
我如何找到这个特定实例的地址...
template<
typename Function,
typename Executor>
void spawn(
const Executor & ex,
Function && function,
const boost::coroutines::attributes & attributes = boost::coroutines::attributes(),
typename enable_if< is_executor< Executor >::value >::type* = 0);
我尝试失败了...
using Exec = boost::asio::io_context;
using Func = std::function<void(boost::asio::yield_context)>;
void (*addr)(Exec, Func) = boost::asio::spawn;
答案 0 :(得分:4)
boost::asio::spawn
不是函数。这是一个 template 函数。这是可以创建功能的蓝图。无法获得指向函数模板的指针,因为它是纯编译时构造。
boost::asio::spawn<Func, Exec>
是一个函数重载集,但没有与签名void(Exec,Func)
匹配的重载。请记住,默认函数参数只是语法糖。这些参数仍然是函数签名的一部分。
这两个问题使获取指向boost::asio::spawn
的指针变得困难而丑陋。使用lambda会容易得多。 Lambda可以让您保留类型推导并利用默认参数:
auto func = [](auto&& exec, auto&& func) {
boost::asio::spawn(std::froward<decltype(exec)>(exec),
std::forward<decltype(func)>(func));
};
即使您绝对需要一个函数指针,lambda仍然可能是您要走的路。您会丢失参数类型推导,但仍可以利用该函数的默认参数:
void(*addr)(const Exec&, Func) = [](const Exec& exec, Func func) {
boost::asio::spawn(exec, std::move(func));
};
之所以可行,是因为可以将无法捕获的lambda转换为原始函数指针。
如果确实出于某种原因,绝对需要直接指向spawn
实例化之一的指针,就可以得到它,但这并不漂亮:
using Exec = boost::asio::io_context::executor_type;
using Func = std::function<void(boost::asio::yield_context)>;
void(*addr)(const Exec&, Func&, const boost::coroutines::attributes&, void*) = boost::asio::spawn<Func&, Exec>;
尽管这样做,您会损失很多。您不仅失去了参数类型推导和默认参数,而且还失去了将左值和右值传递给函数的功能,因为您不再拥有推论工作的推论上下文。我必须获得一个指向接受对该函数的左值引用的实例。如果希望它改为接受右值引用,请使用
void(*addr)(const Exec&, Func&&, const boost::coroutines::attributes&, void*) = boost::asio::spawn<Func, Exec>;
还请注意,此函数采用四个参数。调用它,即
addr(my_io_context.get_executor(), my_function, boost::coroutines::attributes{}, nullptr);
答案 1 :(得分:0)
试图将这种解决方案作为编辑,以便立即解决该问题,但主持人似乎认为最好将读者带到此处...
using Exec = boost::asio::io_context;
using Func = std::function<void(boost::asio::yield_context)>;
using Attr = boost::coroutines::attributes;
void (*addr)(const Exec&,
Func&&,
const Attr&,
typename enable_if< is_executor< Executor >::value>::type*
) = boost::asio::spawn<Func, Exec>;
是的,很丑但是还算不错。