c++ - 无法使方法存在检测机制起作用

标签 c++ c++14 template-meta-programming conditional-compilation

我正在编写模板化代码,它需要调用它获取的仿函数的某个模板化 operator() - 但前提是该 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。

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

注意事项:

  • 模板参数T是任意的;它与 Us 参数无关。
  • 是的,可以使用 operator() 的返回类型派生 R - 但前提是它存在。所以我们只是提供它。
  • 如果启用静态断言 - 它会失败。

最佳答案

你的问题在这里:

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

std::forward采用您未提供的非推导模板参数 - 必须是 forward<T>(u) - 所以它的推论无条件地失败了。

但你甚至不需要 forward在这里。就declval<Us>()足够了。

关于c++ - 无法使方法存在检测机制起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55776371/

相关文章:

c++ - ODR 使用转发的 constexpr 参数?

c++ - 重新分配给尚未准备好的 future 时会发生什么

c++ - 在 C++ 中实现和包装函数组合以进行惰性求值

c++ - 在 Visual Studio 2013 中自动 c++ 源代码格式化

c++ - 从函数返回的错误信息

c++ - 使用 Gradle cpp 插件生成 DLL

c++ - 可变参数模板与使用元组在参数中添加不同的数据对

c++ - 使 C++14 constexpr 函数与 C++11 兼容

c++ - 为什么我不能专门针对依赖类型使用 nullptr 模板参数?

c++ - 使用(n 空)基类在同一个容器中存储不同的对象