首页 文章

std :: result_of无法返回void返回类型

提问于
浏览
1

我正在尝试使用SFINAE来创建函数调用包装器,使用std :: result_of来获取函数的返回类型 . 小样本重现问题:

void test(int) {}

template<typename T, typename... Args, typename R = typename std::result_of<T(Args...)>::type, typename std::enable_if<!std::is_void<R>::value, int>::type* = nullptr>
int test2(R& ret_param, Args... args)
{
    T* test_call = test;
    ret_param = test_call(args...);
    return 0;   
}

template<typename T, typename... Args, typename std::enable_if<std::is_void<typename std::result_of<T(Args...)>::type>::value, int>::type* = nullptr>
int test2(Args... args)
{
    T* test_call = test;
    test_call(args...);
    return 0;   
}

int main()
{
  test2<decltype(test)>(1);
}

用gcc 4.9.2编译这个结果:

68:26: error: no matching function for call to 'test2(int)'
68:26: note: candidates are:
46:5: note: int test2(R&, Args ...) [with T = void(int); Args = {}; R = int; typename std::enable_if<(! std::is_void<R>::value), int>::type* <anonymous> = 0u]
46:5: note:   no known conversion for argument 1 from 'int' to 'int&'
56:5: note: template<class T, class ... Args, typename std::enable_if<std::is_void<typename std::result_of<_Functor(_ArgTypes ...)>::type>::value, int>::type* <anonymous> > int test2(Args ...)
56:5: note:   template argument deduction/substitution failed:
55:142: error: function returning a function
55:142: note: invalid template non-type parameter

那么问题是“typename std :: result_of :: type”以某种方式计算返回函数的函数?如果模板函数的返回类型无效,使用SFINAE强制重载决策选择不同函数的正确方法是什么?值得一提的是,在测试函数返回int的相反情况下 . 另外,如果为std :: is_void解析删除了enable_if,它将在这种情况下工作(但显然如果存在返回类型,则两个函数都将是有效解析,并且当它选择不期望返回值的编译时编译将失败) .

2 回答

  • 1

    基本上你需要形成 T_ref(Args...) 作为std::result_of的参数 .

    以下编译 . 我已经应用了一些简化和重新格式化 .

    顺便说一下,我认为这不是一个好主意 . 相反,只需要 different names 这两个函数 . 毕竟,他们确实需要不同的论点 . 明确是好的 . 隐含是坏事 .

    #include <type_traits>      // std::(enable_if, result_of)
    
    void test(int) {}
    int foo() { return 0; }
    
    template<
        class T,  class R, class... Args,
        class T_ref = T&,
        typename std::enable_if<
            !std::is_void<
                std::result_of_t<T_ref(Args...)>
                >::value
            >::type* = nullptr
        >
    int test2(R& ret_param, Args... args)
    {
        static_assert( std::is_same<
            R,
            std::result_of_t<T_ref(Args...)>
            >::value, "!" );
        T* test_call = foo;
        ret_param = test_call(args...);
        return 0;
    }
    
    template<
        class T, class... Args,
        class T_ref = T&,
        typename std::enable_if<
            std::is_void<
                std::result_of_t<T_ref(Args...)>
                >::value
            >::type* = nullptr
        >
    int test2(Args... args)
    {
        T* test_call = test;
        test_call(args...);
        return 0;   
    }
    
    int main()
    {
        test2<decltype(test)>( 1 );
    
        int result;
        test2<decltype(foo)>( result );
    }
    
  • 1

    如果您接受将测试函数作为参数传递,则不需要所有样板:

    void test(int) {}
    int test(double) { return 0; }
    
    template<typename R, typename... Args>
    int test2(R(&f)(Args...), R& ret_param, Args... args)
    {
        ret_param = f(args...);
        return 0;   
    }
    
    template<typename... Args>
    int test2(void(&f)(Args...), Args... args)
    {
        f(args...);
        return 0;   
    }
    
    int main()
    {
        test2(test, 1);
        int r;
        test2(test, r, .0);
    }
    

    扣除和重载将为您完成工作 .

相关问题