是否可以将"const"变量与非"const"变量以及"const&"引用区分开来?

Is it possible to distinguish a `const` variable from a non-`const` one and from a `const&` reference?

本文关键字:const 变量 引用 区分开 是否      更新时间:2023-10-16

假设我想创建自己的引用("智能指针"(类型,该类型保证始终引用不可变数据,而不仅仅是不可变查看的数据。换句话说,任何人都不能改变的数据,而不是不通过该特定引用。这并不容易,因为C++通常认为const事物是可变访问事物的子情况,并且&引用隐式转换为const &,同样*转换为const *

我们称之为类型:

template<typename T>
class ImmRef { ... };

我可以做的一件简单的事情是声明:

template<typename T>
struct Imm
{
    const T value;
};

然后只允许从Imm s或其他ImmRef中创建ImmRef。这里变量本身被声明为const,所以不可能对它进行任何可变引用,它实际上是不可变的。(除非它在内部使用 mutable ,但由于我们对此无能为力,让我们忽略它。

这是有效的,但是为了更大的灵活性,更广泛的适用性以及与不知道我们Imm类型的其他代码的兼容性,如果我们可以为任何const声明的变量创建ImmRef,那就更好了。但目前尚不清楚C++是否可以区分"声明为const的变量"与"对变量的const引用",甚至与"未声明为const的变量"。

换句话说,这应该有效:

const int myConstNumber = 666;
ImmRef<int> myImmRef = immRef(myConstNumber);

但这不应该:

int myNumber = 666;
ImmRef<int> myImmRef = immRef(myNumber);

这不应该:

const int& myConstRef = myNumber;
ImmRef<int> myImmRef = immRef(myConstRef);

有什么黑暗模板魔法可以让我做到这一点吗?

无法

判断引用引用是指真实的const对象。函数无法判断其参数是命名对象还是引用。

decltype会具体告诉您名称属于const对象(不是引用(,但该名称必须在范围内。此用法不能封装在模板中。

宏可以完成这项工作,如果你真的想要它:

#define MAKE_IMMREF( NAME ) ImmRef< decltype( NAME ) >{ NAME }
template<typename T>
struct ImmRef {
    static_assert ( std::is_const< T >::value, "ImmRef requires a constant." );
    T & ref;
};

演示。