Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::无效返回类型失败的结果_C++_C++11_Variadic Templates_Sfinae - Fatal编程技术网

C++ std::无效返回类型失败的结果

C++ std::无效返回类型失败的结果,c++,c++11,variadic-templates,sfinae,C++,C++11,Variadic Templates,Sfinae,我正在尝试使用SFINAE创建函数调用包装器,使用的std::result_获取函数的返回类型。复制问题的小样本: 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>::ty

我正在尝试使用SFINAE创建函数调用包装器,使用的std::result_获取函数的返回类型。复制问题的小样本:

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);
}
void测试(int){
模板::类型*=nullptr>
int test2(R&ret_参数,Args…Args)
{
T*test\u call=test;
ret_param=测试调用(args…);
返回0;
}
模板
int test2(Args…Args)
{
T*test\u call=test;
测试调用(args…);
返回0;
}
int main()
{
试验2(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
68:26:错误:调用“test2(int)”时没有匹配的函数
68:26:注:候选人为:
46:5:注意:int test2(R&,Args…[带T=void(int);Args={};R=int;typename std::enable_if::type*=0u]
46:5:注意:参数1从'int'到'int&'的转换未知
56:5:注意:模板int test2(Args…)
56:5:注意:模板参数扣除/替换失败:
55:142:错误:函数返回函数
55:142:注意:模板非类型参数无效

那么问题是“typename std::result_of::type”的计算结果是返回函数的函数?如果模板函数的返回类型为void,使用SFINAE强制重载解析选择其他函数的正确方法是什么?值得一提的是,在相反的情况下,测试函数返回一个int。此外,如果为std::is_void解析删除了enable_if,那么它将在这种情况下工作(但显然,如果存在返回类型,那么这两个函数都将是有效的解析,当它选择不需要返回值的函数时,编译将失败)

以下是汇编。我已经应用了一些简化和重新格式化

顺便说一下,我认为这不是个好主意。相反,这两个函数的名称不同。毕竟,他们需要不同的论据。明确是好的。含蓄是不好的

#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 );
}
\include//std::(如果启用,则结果为)
无效测试(int){}
int foo(){return 0;}
模板<
T类,R类,B类。。。Args,
类T_ref=T&,
typename std::启用\u如果<
!std::是否无效<
std::测试结果
>::价值
>::type*=nullptr
>
int test2(R&ret_参数,Args…Args)
{
静态断言(std::是否相同<
R
std::测试结果
>::值“!”;
T*test_call=foo;
ret_param=测试调用(args…);
返回0;
}
模板<
T班,T班。。。Args,
类T_ref=T&,
typename std::启用\u如果<
std::是否无效<
std::测试结果
>::价值
>::type*=nullptr
>
int test2(Args…Args)
{
T*test\u call=test;
测试调用(args…);
返回0;
}
int main()
{
试验2(1);
int结果;
测试2(结果);
}

如果接受通过测试函数作为参数,则不需要所有样板文件:

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);
}
void测试(int){
int测试(双精度){返回0;}
模板
int test2(R&f)(参数…,R&ret_参数,参数…)
{
ret_param=f(args…);
返回0;
}
模板
int test2(无效(&f)(参数…,参数…)
{
f(args…);
返回0;
}
int main()
{
测试2(测试1);
INTR;
test2(test,r,.0);
}

演绎和重载将为您完成这项工作。

首先,
decltype(test)
是一个函数类型,您将它绑定到
T
,在启用逻辑中,它被视为返回类型。我将使用
class
而不是
typename
,并且我将避免使用那些数百个字符行。试着自然地分割东西以便可读。我的理解是std::result_of::type是函数T的返回类型,如果用参数Args调用的话。。。这就是我在启用逻辑中使用的。
T(Args…
,例如
int(char,double)
,是一个返回
T
的函数,带有形式参数
Args…
。哦,等等<代码>标准::定义的的结果_预期会出现这种情况。抱歉,抱歉这个“对不起”:您需要形成T_ref(Args…),其中T_ref是T&。请参阅需求的
std::result\u。一般认为隐式是好的还是显式是坏的,但从抽象上讲,它们做的是相同的事情,所以我希望它们有相同的名称,否则会使其他地方的一堆代码复杂化。感谢这个例子,有没有什么方法可以让我一开始就按ref取T,并避免额外的模板参数?这非常有效,只是想让它看起来比实际情况更漂亮:)您可以在
结果中写入
T&
,而不添加额外的模板参数。感谢您的回答,很遗憾,我无法将函数作为参数传递,因为我只有函数的声明。传递实际函数只会给我链接器错误。只能使用函数的decltype。@好的,您在示例中添加了一个定义,所以我不知道。我很抱歉。