首页 > 解决方案 > c++ 如何定义一个 std::result_of可以处理 R 是无效的

问题描述

当我使用

std::result_of<F(R)>

像这样:

template<typename R, typename... Args>
class Task
{
    //...

    template<typename F>
    auto Then(F&& f) -> Task<typename std::result_of<F(R)>::type(Args...)>
    {  
        //... 
    }    
}; 

由于R是另一个函数的输出类型,所以R可能是void,在这种情况下,会有:

error: invalid parameter type ‘void’.

所以问题是如何处理既是Rvoid不是?

标签: c++c++11templatesvariadic-templatesresult-of

解决方案


选项1

基于 SFINAE:

template <typename F>
class Task;

template <typename R, typename... Args>
class Task<R(Args...)>
{
public:
    template <typename F, typename Ret = R>
    auto Then(F&& f)
        -> typename std::enable_if<!std::is_void<Ret>::value, Task<typename std::result_of<F(Ret)>::type(Args...)>>::type
    {
        return {};
    }

    template <typename F, typename Ret = R>
    auto Then(F&& f)
        -> typename std::enable_if<std::is_void<Ret>::value, Task<typename std::result_of<F()>::type(Args...)>>::type
    {
        return {};
    }
};

演示

选项 #2

类模板的部分特化:

template <typename F>
class Task;

template <typename R, typename... Args>
class Task<R(Args...)>
{
public:
    template <typename F>
    auto Then(F&& f)
        -> Task<typename std::result_of<F(R)>::type(Args...)>
    {
        return {};
    }
};

template <typename... Args>
class Task<void(Args...)>
{
public:
    template <typename F>
    auto Then(F&& f)
        -> Task<typename std::result_of<F()>::type(Args...)>
    {
        return {};
    }
};

演示 2

选项#3

标签调度:

template <typename F>
class Task;

template <typename R, typename... Args>
class Task<R(Args...)>
{    
private:
    template <typename F>
    auto ThenImpl(F&& f, std::true_type)
        -> Task<typename std::result_of<F()>::type(Args...)>
    {
        return {};
    }

    template <typename F, typename Ret = R>
    auto ThenImpl(F&& f, std::false_type)
        -> Task<typename std::result_of<F(Ret)>::type(Args...)>
    {
        return {};
    }

public:
    template <typename F>
    auto Then(F&& f)
        -> decltype(ThenImpl(std::forward<F>(f), std::is_void<R>{}))
    {
        return ThenImpl(std::forward<F>(f), std::is_void<R>{});
    }
};

演示 3


推荐阅读