我已经在这里待了很长时间。基本上,类接受一个类型,它可能是一个函数,还有一些参数:
template <typename T, typename ... Args>
struct HandlerBase
{
HandlerBase(T type, Args ... args) {}
HandlerBase() {}
auto operator()(Args ... args)
{ return std::declval<T>()(args...); } ;
};// This compiles
但现在我想让我的operator()虚拟,我得到错误:
&#34;虚拟成员函数不应具有包含的返回类型 自动&#34;
所以我需要手动设置返回类型,并且在我所有搜索之后我可以尝试的最好:
virtual decltype(std::declval<T>()(std::declval<Args>()...))
operator()(Args ... args)
{ return std::declval<T>()(args...); } ;
或作为追踪回报
virtual auto operator()(Args ... args)
-> decltype(std::declval<T>()(std::declval<Args>()...))
{ return std::declval<T>()(args...); } ;
这些尝试是基于我之前对此主题的一些帮助。我真的觉得通过这样的陈述几乎不可能解析。
如果有人想尝试,这就是整个事情的样子:
#include <iostream>
template <typename T, typename ... Args>
struct HandlerBase
{
HandlerBase(T type, Args ... args) {}
HandlerBase() {}
virtual decltype(std::declval<T>()(std::declval<Args>()...)) operator()(Args ... args)
{ return std::declval<T>()(args...); } ;
};
int main()
{
auto lambda = []() { return 0; };
HandlerBase<decltype(lambda)> object;
}
在正常返回语法和尾随返回语法的Visual Studio上我得到错误我得到一个基本上不可读的链接器错误,但是它提到了返回类型为int的东西,所以我认为我在括号内的实际定义可能是错的。
答案 0 :(得分:2)
std::declval
只能用于未评估的环境中。正如其documentation on cppreference所示:
请注意,因为declval不存在定义,所以它只能是 用于未评估的背景;评估表达式是错误的 包含此功能。在形式上,如果,该计划是不正确的 这个功能很奇怪。
当您编写std::declval<T>()(args...)
时,它会尝试使用引用declval
返回来调用函数调用运算符。这是一个有趣的用途,链接器必须查找它。它无法找到它,因此也就是错误。
只有在添加虚拟说明符时才触发它,因为虚函数是隐式使用的(主要是因为它们必须是为了添加动态调度支持)。
如果没有虚拟说明符,operator()
的函数体将永远不会被实例化,直到尝试调用它(在作为模板类的帐户HandlerBase<>
上)。但如果您尝试在原始版本中调用operator()
,那么您将获得完全相同的链接器错误#34;工作&#34;版本
答案 1 :(得分:1)
您可以使用标准result_of
实现您的需求typename std::result_of<T(Args...)>::type
整个事情看起来像这样:
template <typename T, typename ... Args>
struct HandlerBase
{
HandlerBase(T type, Args ... args) {}
HandlerBase() {}
virtual auto operator()(Args ... args)
-> typename std::result_of<T(Args...)>::type
{ return T()(std::forward<Args>(args)...); };
};
<强>被修改强>
正如所指出的那样,std::result_of
在c ++ 17中被std::invoke_result
替换。
以下是使用std::invoke
和std::invoke_result
的替代实现:
#include <utility>
#include <iostream>
#include <functional>
template <typename T, typename ... Args>
struct HandlerBase
{
HandlerBase() {}
virtual auto operator()(T type, Args ... args)
-> typename std::invoke_result_t<T, Args...>
{ return std::invoke(type, args...); };
};
int main()
{
auto lambda = []() { return 0; };
HandlerBase<decltype(lambda)> object;
}