您如何检测通话结果是否有效

问题描述 投票:0回答:1

我正在尝试创建一个特征,以检测带有2个参数调用的类型Apply的结果。我希望代码中的static_assert不会被击中,因为apply的结果是有效的(除法浮点数)。为什么会断言此命中,以及如何将特征更改为将所有适用的有效重载检测为true_type或constexpr bool true呢?

#include <type_traits>
#include <functional>

struct Apply
{
    template<typename T1, typename T2>
    float apply(const T1& a, const T2& b) const
    {
        return a / b;
    }
};

struct ApplyInvoker
{
    Apply a;

    template<typename... Args>
    auto operator()(Args&&... args)
    {
        return a.apply(std::forward<Args>(args)...);
    }
};

template <class Void, class... T>
struct ValidCall : std::false_type
{ 
};
template <class... T>
struct ValidCall<
    std::void_t<decltype(std::invoke(std::declval<ApplyInvoker>(), std::declval<T>()...))>, 
    T...> 
    : std::true_type
{ 
};

template<typename T1, typename T2>
constexpr bool CanApply = ValidCall<void, T1, T2>::value;

int main()
{
    static_assert(CanApply<float, float>);
}
c++ templates c++17 constexpr typetraits
1个回答
0
投票

您将模板用作:

template<typename T1, typename T2>
constexpr bool CanApply = ValidCall<T1, T2>::value;

但是主变量声明为:

template <class Void, class... T>
struct ValidCall;

该第一个模板参数被命名为Void,因为它已经void-这是专业化所要匹配的。所以你必须这样做:

template<typename T1, typename T2>
constexpr bool CanApply = ValidCall<void, T1, T2>::value;
//                                  ^~~~

而且也是C ++ 17,为此,我们具有类型特征:

template<typename T1, typename T2>
constexpr bool CanApply = std::is_invocable_v<ApplyInvoker, T1, T2>;

问题是ApplyApplyInvoker都无法真正使用类型特征。 Apply宣称自己可以被任何两个参数调用-否则无法检测。 ApplyInvoker宣传自己可以使用任意数量的参数,但是如果您尝试使用错误的参数集,这种方式将导致编译器出现错误。这两种类型都是我们称之为SFINAE不友好的类型-它们对特征类型不友好,无法测试。

如果您希望它们实际上是可测试的,那么您需要按如下方式重写它们:

struct Apply
{
    template<typename T1, typename T2>
    float apply(const T1& a, const T2& b) const
        -> decltype(float(a / b))
    {
        return a / b;
    }
};

struct ApplyInvoker
{
    Apply a;

    template <typename... Args>
    auto operator()(Args&&... args)
        -> decltype(a.apply(std::forward<Args>(args)...)
    {
        return a.apply(std::forward<Args>(args)...);
    }
};

或类似的东西。

© www.soinside.com 2019 - 2024. All rights reserved.