【发布时间】:2019-11-03 02:19:53
【问题描述】:
我正在尝试创建一个转发包装函数,该函数对c++14 中的函数调用进行计时。我需要处理 2 类型,
一个正在计时一个不返回值的函数,并且
其他未返回
在此处跳过的调用前后可能需要执行一些操作,因此我不能只返回func(),它同时处理void 和non-void 类型。
这是void 函数的包装器。
template<typename T, typename ...U>
auto time_function(T&& func, U&& ...args) -> typename enable_if<is_same<decltype(func(args...)), void>::value>::type
{
std::cout << "timing void function" << std::endl;
std::forward<T>(func)(std::forward<U>(args)...);
std::cout << "timing over" << std::endl;
}
non-void 函数的包装器
template<typename T, typename ...U>
auto time_function(T&& func, U&& ...args) -> typename enable_if < !is_same<decltype(func(args...)), void), decltype(func(args...)) > ::value > ::type
{
std::cout << "timing returning function" << std::endl;
auto val = std::forward<T>(func)(std::forward<U>(args)...);
std::cout << "timing over" << std::endl;
return val;
}
int main()
{
time_function(foo, 2);
int i = time_function(&foo_return, 1); //this generates an error
//std::cout<<i<<std::endl;
}
foo 是一个返回void 的函数,foo_return 返回一个整数。
产生的错误是
<source > :28 : 129 : error : template argument 1 is invalid
auto time_function(T && func, U && ...args) -> typename enable_if<!is_same<decltype(func(args...)), void>, decltype(func(args...))>::value > ::type
^
<source>:28 : 55 : error : expected nested - name - specifier before 'enable_if'
auto time_function(T && func, U && ...args) -> typename enable_if<!is_same<decltype(func(args...)), void>, decltype(func(args...))>::value > ::type
^ ~~~~~~~~
<source>:28 : 129 : error : template argument 1 is invalid
auto time_function(T && func, U && ...args) -> typename enable_if<!is_same<decltype(func(args...)), void>, decltype(func(args...))>::value > ::type
^
<source>:28 : 129 : error : template argument 1 is invalid
<source> : 28 : 129 : error : template argument 1 is invalid
<source> : 28 : 55 : error : expected initializer before 'enable_if'
auto time_function(T && func, U && ...args) -> typename enable_if<!is_same<decltype(func(args...)), void>, decltype(func(args...))>::value > ::type
^ ~~~~~~~~
<source>: In function 'int main()' :
<source> : 42 : 41 : error : no matching function for call to 'time_function(int (*)(int), int)'
int i = time_function(&foo_return, 1); //error -
^
<source>:20 : 6 : note : candidate : template<class T, class ... U> typename std::enable_if<std::is_same<decltype (func(time_function::args ...)), void>::value>::type time_function(T&&, U && ...)
auto time_function(T && func, U && ...args) -> typename enable_if<is_same<decltype(func(args...)), void>::value>::type
^ ~~~~~~~~~~~~
<source> : 20 : 6 : note : template argument deduction / substitution failed :
<source> : In substitution of 'template<class T, class ... U> typename std::enable_if<std::is_same<decltype (func(time_function::args ...)), void>::value>::type time_function(T&&, U&& ...) [with T = int (*)(int); U = {int}]' :
<source> : 42 : 41 : required from here
<source> : 20 : 6 : error : no type named 'type' in 'struct std::enable_if<false, void>'
据我所知,包装是正确的,有什么问题?我正在使用is_same 检查函数的返回类型是否为void,如果是,则声明我希望使用enable_if 的返回类型。
【问题讨论】:
-
我会避免在
decltype中使用的f(args...)和函数中实际调用的std::forward<T>(func)(std::forward<U>(args)...)之间存在差异。您可能有一个有效的和一个无效的,或者它们可能是两个不同的函数,其中一个返回void而另一个不返回。 -
@aschepler 当我进行转发时,它只是执行函数的条件静态转换,对吗?怎么可能是2个不同的功能或无效?
-
例如,给定
void f1(std::string&&);并尝试执行time_function(f1, std::string{});然后f1(arg)无效但f1(std::forward<std::string>(arg))有效。给定void f2(std::string&);,则f2(arg)有效,但f2(std::forward<std::string>(arg))无效。如果f3有一个具有void operator()(std::string&);和int operator()(std::string&&);的类类型,那么enable_if会看到返回类型void,但主体调用返回类型为int的函数。 -
我理解将args转发给函数,但是函数本身呢?
标签: c++14 c++ templates c++14 sfinae function-templates