有可能区分一个`const`变量和一个非`constst`变量和一个`const&`引用?

时间:2014-12-06 02:10:39

标签: c++ reference const immutability sfinae

假设我想创建自己的引用("智能指针")类型,保证始终引用不可变数据,而不仅仅是不可见的数据。换句话说,任何人都不能突变的数据,而不是仅通过该特定参考。这并不容易,因为C ++通常会将const事物视为可变访问事物的子案例,而&引用会隐式转换为const &,同样*转换为const * {1}}。

我们称之为:

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

我能做的一件简单事就是声明:

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

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

虽然有效,但为了获得更大的灵活性,更广泛的适用性以及与我们对Imm类型无关的其他代码的兼容性,如果我们可以创建ImmRef s会更好到任何 const - 声明的变量。但是,目前还不清楚C ++是否能够区分一个声明为const&#34;的变量。来自&#34; const对变量&#34;的引用,甚至来自&#34;未声明为const&#34;的变量。

换句话说,这应该有效:

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);

是否有任何黑暗模板魔法让我这样做?

1 个答案:

答案 0 :(得分:1)

没有办法告诉引用引用真正的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;
};

Demo.