关于我尝试做的一些背景:我正在尝试实现一个做量子力学的库.由于量子力学基本上只是线性代数,我使用下面的犰狳线性代数库.Armadillo使用惰性求值来对矩阵做一些聪明的技巧,这样可以很好地抽象出实际情况并且看起来接近matlab代码.
我想做类似的事情,但我也希望能够使用auto
,这是犰狳(或本征)无法实现的.
我一直在寻找一下,这个答案包含了我认为实现这个的典型方法:https://stackoverflow.com/a/414260/6306265
这种方法的问题在于你写的时候
auto C = A+B;
Run Code Online (Sandbox Code Playgroud)
你得到的C
是一个matrix_add
,而不是一个matrix
.即使matrix_add
表现得足够相似matrix
,matrix_add
包含引用A
并B
使其难以随身携带的事实.例如
auto A = matrix(2,2,{0,1,0,1});
auto B = matrix(2,2,{1,0,1,0});
auto C = A+B;
C.printmatrix(); // 1,1 ; 1,1
Run Code Online (Sandbox Code Playgroud)
但
auto A = matrix(2,2,{0,1,0,1});
auto B = matrix(2,2,{1,0,1,0});
auto C = A+B;
A(0,0) = 1;
C.printmatrix(); // 2,1 ; 1,1
Run Code Online (Sandbox Code Playgroud)
这是违反直觉的.由于数学上直观的行为是我想要实现的,这是一个问题.
更糟糕的是当我这样做
auto sumMatrices(const matrix& A, const matrix& B)
{
return A+B; …
Run Code Online (Sandbox Code Playgroud) 在我正在设计的库中,我有时需要对类的大型成员变量进行读取访问。由于它们的大小,我不想创建一个通过复制成员来返回的 getter。我不希望它们可以从外部修改,所以我不能将它们公开或返回对它们的引用。所以我想我会使用“阅读器”:
class TestClass
{
public:
explicit TestClass(double d): d_(d){}
const double& readD() const { return d_; }
private:
double d_;
};
Run Code Online (Sandbox Code Playgroud)
(这并不是真正适合双打的)
但这里有人可以 const_cast 引用并直接访问数据。即使没有假设恶意意图,有人也可以保护对数据成员的引用,并在原始对象超出范围后保留它。我知道 const 引用可以保持临时可行,但这并不能消除 const_cast 问题。所以我想出了一个解决方法:
#include <iostream>
template<class T>
class SafeMemberReference
{
public:
using type = T;
SafeMemberReference(const T& t) :t(t) {}
explicit SafeMemberReference(T&& t) = delete;
operator const T& () && {return t; }
T get() && {return t; }
private:
const T& t;
};
class TestClass
{
public:
explicit TestClass(double d): d_(d){}
SafeMemberReference<double> …
Run Code Online (Sandbox Code Playgroud)