首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用`std::enable_if`失败的转发包装器

使用`std::enable_if`失败的转发包装器
EN

Stack Overflow用户
提问于 2019-11-03 02:19:53
回答 1查看 175关注 0票数 2

我正在尝试创建一个转发包装器函数,它会在c++14中调用一个函数。我需要处理一些2类型,

  • 一种是计时不返回值的函数,以及
  • 其他不返回

在这里跳过的调用之前和之后,可能需要执行一些操作,所以不能只返回func(),它同时处理voidnon-void类型。

下面是void函数的包装器。

代码语言:javascript
复制
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函数的包装器

代码语言:javascript
复制
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返回一个整数。生成的错误是

代码语言:javascript
复制
<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>'

据我所知,包装是正确的,有什么问题吗?我正在检查函数的返回类型是否为使用voidis_same,如果是,则使用enable_if声明希望的返回类型。

EN

回答 1

Stack Overflow用户

发布于 2019-11-03 08:06:42

https://stackoverflow.com/questions/58676930/forwarding-wrapper-using-enable-if-failing/58677000#58677000已经指出了语法错误。不过,我想提几点改善措施。

由于您使用的是c++14,所以可以使用std::enable_if的较少冗长的版本,通过使用std::enable_if_t实现相同的目的。

其次,std::is_void是检查某一类型是否为void的标准中较好(或合适)的特性,这也将节省一些类型。使用可变模板 (也是自c++14之后),这将大大缩短!

代码语言:javascript
复制
#include <iostream>
#include <type_traits> // std::enable_if_t, std::is_void
// variable templates
template<class T> constexpr bool is_void_v = std::is_void<T>::value;

template<typename T, typename ...U>
auto time_function(T&& func, U&& ...args) -> std::enable_if_t<::is_void_v<decltype(func(args...))>>
{
    // ... code here
}

template<typename T, typename ...U>
auto time_function(T&& func, U&& ...args)
-> std::enable_if_t<!::is_void_v<decltype(func(args...))>, decltype(func(args...))>
{
    // ... code here
}

但是,如果您可以访问c++17,可以使用if constexpr在一个函数中编写这两个逻辑。只是为了未来@待办事项清单。(看这里的生活)

代码语言:javascript
复制
#include <type_traits> // std::enable_if_t, std::is_void_v

template<typename T, typename ...U>
auto time_function(T&& func, U&& ...args)
{
    if constexpr (std::is_void_v<decltype(func(args...))>)
    {
        // ... timing void function"
    } 
    else
    {
        // ... timing returning function
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58676930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档