c++ 如何定义可以处理 R 的 std::result_of<F(R)> 是无效的

c++ how to define a std::result_of<F(R)> that can handle R is void

当我使用

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 而不是?

选项#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 {};
    }
};

DEMO

选项#2

class 模板的部分专业化:

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 {};
    }
};

DEMO 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>{});
    }
};

DEMO 3