尝试使用std :: result_of时编译错误

时间:2017-03-25 16:05:03

标签: c++ c++11 typetraits

我想推断出作为模板参数的函数的返回类型。请考虑以下代码:

#include <type_traits>

struct Result {};

Result foo() { return Result{}; }

template<typename Factory>
void check(Factory) {
    using ActualResult = typename std::result_of<Factory()>::type;
    static_assert(std::is_same<Result, ActualResult>::value, "");
}

int main() {
    check(foo);
}

这可以按预期工作。但是,如果我将check()的参数更改为const Factory&,则它不会编译。 gcc的错误是:

prog.cc: In instantiation of 'void check(const Factory&) [with Factory = Result()]':
prog.cc:14:14:   required from here
prog.cc:9:66: error: function returning a function
     using ActualResult = typename std::result_of<Factory()>::type;
                                                                  ^
prog.cc:10:65: error: function returning a function
     static_assert(std::is_same<Result, ActualResult>::value, "");
                                                                 ^

这里有什么问题?我怎样才能使它发挥作用?

1 个答案:

答案 0 :(得分:2)

函数(就像数组一样)既不能作为prvalue参数传递,也不能作为prvalues返回。

因此,带有prvalue参数的template <typename Factory> void check(Factory)会导致foo衰减到函数指针,而check(foo)会导致Factory推断为{Result (*)() 1}}。最后,result_of<Factory()>给出了调用可调用类型的结果,该类型是没有参数的函数指针。

当您将check更改为check(const Factory&)时,该函数采用左值,因此没有衰减,Factory被推断为函数类型Result()。这不是允许传递给result_of *的类型,它需要可调用类型或对函数的引用。也就是说,在这种情况下你应该使用result_of<Factory&()>

*)在C ++ 11中。 result_of的规则可能在以后的修订中放宽了,C ++ 17弃用了result_of