c++ 确定传递给模板的可调用对象的返回类型

n3h0vuf2  于 2022-11-27  发布在  其他
关注(0)|答案(1)|浏览(119)

我有一个简单的 Package 器模板,它允许自由函数(例如open()close()等)作为模板参数传递。代码如下:

template <auto fn, typename ReturnType=void>
struct func_wrapper {

    template<typename... Args>
    constexpr ReturnType operator()(Args&&... args) const {
        if constexpr( std::is_same<ReturnType, void>::value) {
            fn(std::forward<Args>(args)...);
        } else {
            return fn(std::forward<Args>(args)...);
        }
    }
};

其用法如下:

void CloseFunc2(int a);
    into OpenFunc2(const std::string&, int flags);

    using FileWrapper2 = DevFileWrapper<func_wrapper<OpenFunc2, int>,
                                        func_wrapper<CloseFunc2>>;

代码运行良好,但我想删除在创建func_wrapper时手动指定ReturnType的要求。
我尝试使用std::result_of,但失败了,因为fn是非类型模板参数,例如:

template<typename... Args>
constexpr auto operator()(Args&&... args) const 
    -> std::invoke_result<fn(std::forward<Args>(args)...)>::type {
    if constexpr( std::is_same<ReturnType, void>::value) {
        fn(std::forward<Args>(args)...);
    } else {
        return fn(std::forward<Args>(args)...);
    }
}

错误为:

template-parameter-callable.cpp:48:71: error: template argument for 
template type parameter must be a type
constexpr auto operator()(Args&&... args) const ->   
    std::invoke_result<fn(std::forward<Args>(args)...)>::type {                                                                           
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/
usr/include/c++/v1/type_traits:4009:17: 
note: template parameter is declared here
template <class _Fn, class... _Args>
                ^

1 error generated.

如何推导编译时调用fn的返回类型?

tag5nh1u

tag5nh1u1#

template <auto fn>
struct func_wrapper {
    template<typename... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
      return fn(std::forward<Args>(args)...);
    }
};

你试过这个吗?
我认为这在c++17中有效。绝对在c++20中。
除非您也知道用来呼叫可呼叫对象的参数,否则无法判断可呼叫对象的传回型别。
我可以提取返回类型,但我认为您不需要它。

template <auto fn>
struct func_wrapper {
    template<typename... Args>
    constexpr decltype(auto) operator()(Args&&... args) const {
      using ReturnType = std::invoke_result_t<
        decltype(fn),
        Args&&...
      >;
      return fn(std::forward<Args>(args)...);
    }
};

但你也看到了我们不需要它。
f返回void时,return f(x)(现在)法律的。

相关问题