代码之家  ›  专栏  ›  技术社区  ›  einpoklum

无法使方法存在性检测机制工作

  •  1
  • einpoklum  · 技术社区  · 5 年前

    operator() 但前提是 运算符() 存在。

    
    template <typename>
    struct sfinae_true : std::true_type{};
    
    template <class F, typename T, typename... Us>
    static auto test_templated_invoke_operator(int) ->
        sfinae_true<decltype(std::declval<F>().template operator()<T>(std::forward(std::declval<Us>())... ))>;
    
    template <class, typename, typename... Us>
    static auto test_templated_invoke_operator(long) -> std::false_type;
    
    template <class F, typename T, typename... Us>
    struct has_templated_invoke_operator : decltype( test_templated_invoke_operator<F, T, Us...>(int{}) )
    { };
    
    template <bool ActuallyInvoke, typename R, class F, typename T, typename... Ts>
    struct invoke_if_possible_inner;
    
    template <class F, typename R, typename T, typename... Ts>
    struct invoke_if_possible_inner<false, R, F, T, Ts...>
    {
        R operator()(F, Ts&&...) { 
            return R(); 
        }
    };
    
    template <class F, typename R, typename T, typename... Ts>
    struct invoke_if_possible_inner<true, R, F, T, Ts...>
    {
        R operator()(F functor, Ts&&... params)
        {
            return functor.template operator()<T>(std::forward<Ts>(params)...);
        }
    };
    
    template <typename T, typename R>
    struct invoke_if_possible {
        template <class F, typename... Ts>
        R operator()(F functor, Ts&&... params)
        {
            constexpr bool actually_invoke = has_templated_invoke_operator<F, T, Ts...>::value;
            // static_assert(actually_invoke == true,"Should be able to invoke for now!");
            return invoke_if_possible_inner<actually_invoke, R, F, T, Ts...>{}(functor, std::forward<Ts>(params)...);
        }
    };
    

    这里有一个小的 main() 用于测试的函数:

    int main() 
    {
        invoke_if_possible<int, double> iip;
        auto result = iip(foo{}, 3.0);
        std::cout << "Invoke if possible result is " << result << " (and should be 6.0)" << std::endl;
    }
    

    fails (Coliru)-返回0.0而不是6.0。

    我的问题是:为什么代码不调用定义的操作符()?我如何修复检测机制,以便确认它的存在并调用它?

    笔记:

    • 模板参数T是任意的;它与 Us 参数。
    • 运算符() -但前提是它存在。所以我们只提供它。
    1 回复  |  直到 5 年前
        1
  •  4
  •   Barry    5 年前

    你的问题是:

    std::forward(std::declval<Us>())
    

    std::forward forward<T>(u) -因此,它的演绎无条件地失败了。

    但你甚至不需要 forward declval<Us>() 够了。