使用具有无效参数类型的invoke_result吗?

时间:2019-01-07 11:10:38

标签: c++ c++17 void result-of declval

我正在尝试执行以下操作:

struct Unwrapper
{
    template<typename T>
    auto operator()(const T& arg, std::enable_if_t<isPrimitive<T>, void>* = nullptr) {return arg;}

    template<typename T>
    auto operator()(const T& arg, std::enable_if_t<!isPrimitive<T>, void>* = nullptr) {return arg.wrapped();}

    void operator()(void) {}
};

template<typename T>
using UnwrappedT = std::invoke_result_t<Unwrapper, T>; // error: no type named ‘type’ in ‘struct std::invoke_result<Unwrapper, void>’

docs for std::invoke_result建议它应在Argsvoid(即无)的情况下工作,特别是说无效的情况不起作用是对已弃用的{{1 }}。

但是没有,std::result_of不起作用。之所以说这样有道理,是因为void也不能做std::declval<T>(),而T = void应该以{{1​​}}的方式实现。

问题是,修补代码以使其无效的最优雅/直接的方法是什么?我可以用std::invoke_result做些什么,但我希望更好。 (使用C ++ 17)

相关问题:thisthis

1 个答案:

答案 0 :(得分:1)

您可以这样做:

template<typename... T>
using UnwrappedT = std::invoke_result_t<Unwrapper, T...>; 

UnwrappedT<>将处理void情况。

如果您希望UnwrappedT<void>的意思是UnwrappedT<>,则需要某种删除void的方法。 conditional是最熟悉的做法:

template<typename T>
using UnwrappedT = typename std::conditional_t<
    std::is_void_v<T>,
    std::invoke_result<Unwrapper>,
    std::invoke_result<Unwrapper, T>>::type;

或者您可以在Boost.Mp11上找到一些乐趣:

template<typename T>
using UnwrappedT = mp_apply<std::invoke_result_t,
    mp_remove_if<mp_list<Unwrapper, T>, std::is_void>>;