You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Eigen中unaryExpr调用同结构体成员函数编译失败问题

问题:Eigen unaryExpr调用类成员函数编译失败

问题重现

当sigmoid为全局函数时,代码可正常编译运行:

#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <Eigen/Core>

#include <iostream>

using Eigen::MatrixXd, std::cout, std::cin;

double sigmoid(double x) {
    return 1.0 / (1.0 + exp(-x));
}

struct Network {
public:
    MatrixXd sigmoid_matrix(MatrixXd z) {
        return z.unaryExpr(&sigmoid);
    }
};

int main() {
    Network net;
    Eigen::MatrixXd m(1, 4);
    m << 1, 2, 3, 4;
    cout << net.sigmoid_matrix(m);
}

但将sigmoid移入Network结构体作为非静态成员函数后,编译失败:

#include <Eigen/Dense>
#include <Eigen/Sparse>
#include <Eigen/Core>

#include <iostream>

using Eigen::MatrixXd, std::cout, std::cin;

struct Network {
public:
    double sigmoid(double x) {
        return 1.0 / (1.0 + exp(-x));
    }
    MatrixXd sigmoid_matrix(MatrixXd z) {
        return z.unaryExpr(&Network::sigmoid);
    }
};

int main() {
    Network net;
    Eigen::MatrixXd m(1, 4);
    m << 1, 2, 3, 4;
    cout << net.sigmoid_matrix(m);
}

核心报错信息

D:/Projects/c++/eigen/Eigen/src/Core/util/Meta.h:272:61: error: no type named 'type' in 'struct std::invoke_result<double (Network::*)(double), const double&>'
  272 |   typedef typename std::invoke_result<F, ArgTypes...>::type type1;
      |                                                             ^~~~~
D:/Projects/c++/eigen/Eigen/src/Core/util/Meta.h:273:31: error: no type named 'type' in 'struct std::invoke_result<double (Network::*)(double), const double&>'
  273 |   typedef remove_all_t<type1> type;
      |                               ^~~~

完整报错信息

PS D:\Projects\c++\NeuralNetwrokNumbers> g++ -I D:/Projects/c++/eigen network.cpp -o network.exe
In file included from D:/Projects/c++/eigen/Eigen/Core:169,
                 from D:/Projects/c++/eigen/Eigen/Dense:1,
                 from network.cpp:1:
D:/Projects/c++/eigen/Eigen/src/Core/util/Meta.h: In instantiation of 'struct Eigen::internal::result_of<double (Network::*(const double&))(double)>':
D:/Projects/c++/eigen/Eigen/src/Core/CwiseUnaryOp.h:26:28:   required from 'struct Eigen::internal::traits<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >'
D:/Projects/c++/eigen/Eigen/src/Core/CwiseUnaryOp.h:97:7:   required from 'class Eigen::CwiseUnaryOpImpl<double (Network::*)(double), const Eigen::Matrix<double, -1, -1>, Eigen::Dense>'
D:/Projects/c++/eigen/Eigen/src/Core/CwiseUnaryOp.h:58:7:   required from 'class Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> >'     
network.cpp:19:27:   required from here
D:/Projects/c++/eigen/Eigen/src/Core/util/Meta.h:272:61: error: no type named 'type' in 'struct std::invoke_result<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> >'
D:/Projects/c++/eigen/Eigen/src/Core/util/Meta.h:273:31: error: no type named 'type' in 'struct std::invoke_result<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> >'
In file included from D:/Projects/c++/eigen/Eigen/Core:292:
D:/Projects/c++/eigen/Eigen/src/Core/DenseBase.h: In instantiation of 'class Eigen::DenseBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >':
D:/Projects/c++/eigen/Eigen/src/Core/MatrixBase.h:51:34:   required from 'class Eigen::MatrixBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >'
D:/Projects/c++/eigen/Eigen/src/Core/CwiseUnaryOp.h:97:7:   required from 'class Eigen::CwiseUnaryOpImpl<double (Network::*)(double), const Eigen::Matrix<double, -1, -1>, Eigen::Dense>'
D:/Projects/c++/eigen/Eigen/src/Core/CwiseUnaryOp.h:58:7:   required from 'class Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> >'     
network.cpp:19:27:   required from here
D:/Projects/c++/eigen/Eigen/src/Core/DenseBase.h:79:17: error: 'coeff' has not been declared in 'Eigen::DenseBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   79 |     using Base::coeff;
      |                 ^~~~~
D:/Projects/c++/eigen/Eigen/src/Core/DenseBase.h:80:17: error: 'coeffByOuterInner' has not been declared in 'Eigen::DenseBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   80 |     using Base::coeffByOuterInner;
      |                 ^~~~~~~~~~~~~~~~~
D:/Projects/c++/eigen/Eigen/src/Core/DenseBase.h:81:26: error: 'operator()' has not been declared in 'Eigen::DenseBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   81 |     using Base::operator();
      |                          ^
D:/Projects/c++/eigen/Eigen/src/Core/DenseBase.h:82:26: error: 'operator[]' has not been declared in 'Eigen::DenseBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   82 |     using Base::operator[];
      |                          ^
D:/Projects/c++/eigen/Eigen/src/Core/DenseBase.h:83:17: error: 'x' has not been declared in 'Eigen::DenseBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   83 |     using Base::x;
      |                 ^
D:/Projects/c++/eigen/Eigen/src/Core/DenseBase.h:84:17: error: 'y' has not been declared in 'Eigen::DenseBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   84 |     using Base::y;
      |                 ^
D:/Projects/c++/eigen/Eigen/src/Core/DenseBase.h:85:17: error: 'z' has not been declared in 'Eigen::DenseBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   85 |     using Base::z;
      |                 ^
D:/Projects/c++/eigen/Eigen/src/Core/DenseBase.h:86:17: error: 'w' has not been declared in 'Eigen::DenseBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   86 |     using Base::w;
      |                 ^
In file included from D:/Projects/c++/eigen/Eigen/Core:293:
D:/Projects/c++/eigen/Eigen/src/Core/MatrixBase.h: In instantiation of 'class Eigen::MatrixBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, 
-1, -1> > >':
D:/Projects/c++/eigen/Eigen/src/Core/CwiseUnaryOp.h:97:7:   required from 'class Eigen::CwiseUnaryOpImpl<double (Network::*)(double), const Eigen::Matrix<double, -1, -1>, Eigen::Dense>'
D:/Projects/c++/eigen/Eigen/src/Core/CwiseUnaryOp.h:58:7:   required from 'class Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> >'     
network.cpp:19:27: required from here
D:/Projects/c++/eigen/Eigen/src/Core/MatrixBase.h:78:17: error: 'coeff' has not been declared in 'Eigen::MatrixBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   78 |     using Base::coeff;
      |                 ^~~~~
D:/Projects/c++/eigen/Eigen/src/Core/MatrixBase.h:81:17: error: 'eval' has not been declared in 'Eigen::MatrixBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   81 |     using Base::eval;
      |                 ^~~~
D:/Projects/c++/eigen/Eigen/src/Core/MatrixBase.h:82:25: error: 'operator-' has not been declared in 'Eigen::MatrixBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   82 |     using Base::operator-;
      |                         ^
D:/Projects/c++/eigen/Eigen/src/Core/MatrixBase.h:85:25: error: 'operator*=' has not been declared in 'Eigen::MatrixBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   85 |     using Base::operator*=;
      |                         ^~
D:/Projects/c++/eigen/Eigen/src/Core/MatrixBase.h:86:25: error: 'operator/=' has not been declared in 'Eigen::MatrixBase<Eigen::CwiseUnaryOp<double (Network::*)(double), const Eigen::Matrix<double, -1, -1> > >::Base'
   86 |     using Base::operator/=;
      |                         ^~

编译失败原因

非静态成员函数的调用依赖于类的实例对象:C++中,非静态成员函数会隐式接收一个this指针作为第一个参数,用来指向当前调用的类实例。而Eigen的unaryExpr方法只会向传入的可调用对象传递矩阵的单个元素,无法提供成员函数所需的this指针,导致参数不匹配。

核心报错中的std::invoke_result错误,本质就是编译器无法用const double&(矩阵元素)去调用需要Network*+double参数的成员函数double (Network::*)(double),因此无法推导返回类型。后续的一系列报错都是这个核心问题引发的连锁反应。

解决方案

方案1:将sigmoid改为静态成员函数

静态成员函数不依赖类实例,不需要this指针,可以直接作为函数指针传递给unaryExpr:

#include <Eigen/Dense>
#include <iostream>

using Eigen::MatrixXd, std::cout;

struct Network {
public:
    static double sigmoid(double x) {  // 改为static
        return 1.0 / (1.0 + exp(-x));
    }
    MatrixXd sigmoid_matrix(MatrixXd z) {
        return z.unaryExpr(&Network::sigmoid);  // 直接传递静态成员函数指针
    }
};

int main() {
    Network net;
    Eigen::MatrixXd m(1, 4);
    m << 1, 2, 3, 4;
    cout << net.sigmoid_matrix(m);
}

方案2:使用lambda表达式捕获this

通过lambda捕获当前对象的this指针,在lambda内部调用成员函数,lambda可以直接被unaryExpr接受:

#include <Eigen/Dense>
#include <iostream>

using Eigen::MatrixXd, std::cout;

struct Network {
public:
    double sigmoid(double x) {
        return 1.0 / (1.0 + exp(-x));
    }
    MatrixXd sigmoid_matrix(MatrixXd z) {
        // 捕获this,在lambda中调用成员函数
        return z.unaryExpr([this](double x) { return this->sigmoid(x); });
    }
};

int main() {
    Network net;
    Eigen::MatrixXd m(1, 4);
    m << 1, 2, 3, 4;
    cout << net.sigmoid_matrix(m);
}

方案3:使用std::bind绑定this指针

用std::bind将this指针和成员函数绑定,生成一个适配后的可调用对象:

#include <Eigen/Dense>
#include <iostream>
#include <functional>  // 需要包含bind的头文件

using Eigen::MatrixXd, std::cout, std::bind;

struct Network {
public:
    double sigmoid(double x) {
        return 1.0 / (1.0 + exp(-x));
    }
    MatrixXd sigmoid_matrix(MatrixXd z) {
        // 绑定this指针到成员函数
        return z.unaryExpr(bind(&Network::sigmoid, this, std::placeholders::_1));
    }
};

int main() {
    Network net;
    Eigen::MatrixXd m(1, 4);
    m << 1, 2, 3, 4;
    cout << net.sigmoid_matrix(m);
}

内容的提问来源于stack exchange,提问作者Fisteshak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 16:07:02