将 std::forward 与 Eigen::Ref 对象一起使用

Use of std::forward with Eigen::Ref objects

我有一个仿函数 Foo 定义如下:

struct Foo {
    template <typename _Vector>
    void operator()(const Eigen::Ref<const _Vector>&, const Eigen::Ref<const _Vector>&) {
        /* ... */
    }
};

我想用特征向量、块或 Eigen::Ref 来调用它,_Vector 可以是任何特征向量类型。此实现不起作用,因为您必须使用 Eigen::Ref<const _Vector> 个参数调用它 exactly -- 而不是,例如,使用向量或向量段。我发现的解决方法如下:

struct Foo {
    /* This works, but I'm not sure if it is the most correct solution. */
    template <typename T, typename U>
    void operator()(const T& x, const U& y) {
        Impl<typename T::PlainObject>(x, y);
    }

    /* This doesn't work, but I expected this to be the most correct solution. */
    // template <typename T, typename U>
    // void operator()(T&& x, U&& y) {
    //     Impl<typename T::PlainObject>(std::forward<T>(x), std::forward<U>(y));
    // }

    template <typename _Vector>
    void Impl(const Eigen::Ref<const _Vector>&, const Eigen::Ref<const _Vector>&) {
        /* ... */
    }
};

在这里,我将实现隐藏在函数 Impl 中,并用 operator() 捕获每个参数;然后,我从第一个参数 (x) 的成员类型 PlainObject 中推导出正确的 _Vector 类型。但是,我希望注释代码更“正确”,因为它完美地转发了参数,以便 Impl 使用它们时完全按照预期的方式使用。 这个断言是错误的吗?不幸的是,它失败并出现以下错误:

error: ‘Eigen::Ref<Eigen::Matrix<double, -1, 1> >&’ is not a class, struct, or union type
[build]   390 |         Impl<typename T::PlainObject>(std::forward<T>(x), std::forward<U>(y));
[build]       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

它声明 Eigen::Ref 不是 class、结构或联合类型;但它实际上是一个class。 如何解决这个错误?

P.S.: 我必须承认我不是 100% 有把握理解什么时候应该使用 T&&std::forward。我的理解是,它们会准确地为您提供您传递的内容,而无需额外的副本或隐式转换。

error: ‘Eigen::Ref<Eigen::Matrix<double, -1, 1> >&’ is not a class, struct, or union type
                                                 ^

您需要std::remove_reference使完美转发的版本生效:

#include <type_traits>

template <typename T, typename U>
void operator()(T&& x, U&& y) {
     Impl<typename std::remove_reference_t<T>::PlainObject>(std::forward<T>(x),
                                                            std::forward<U>(y));
}