一个对象可以知道自己的常量性?(Can an object know its own constne

2019-07-21 04:08发布

decltypestd::is_const可以从外部检测到一个变量的常量性。 但是,它也有可能的对象知道自己的常量性? 使用方法应该是这样的:

#include <type_traits>
#include <iostream>
#include <ios>

struct Test
{
    Test() {}

    bool print() const
    {
       // does not work as is explained in https://stackoverflow.com/q/9890218/819272
       return std::is_const<decltype(*this)>::value; // <--- what will work??
    }
};

int main()
{
    Test t;
    const Test s;

    // external constness test
    std::cout << std::boolalpha << std::is_const<decltype(t)>::value << "\n";
    std::cout << std::boolalpha << std::is_const<decltype(s)>::value << "\n";

    // internal constness test
    std::cout << std::boolalpha << t.print() << "\n";
    std::cout << std::boolalpha << s.print() << "\n"; // <--- false??
}

输出LiveWorkSpace这在某种程度上可能吗?

动机 :我希望能够检测一个const成员函数是否被调用const对象上,或者从非const对象的到来。 该对象可以是例如代表一个缓存和构件的视图。 如果缓存为常量,一个大概可以使用优化的抽奖程序,而如果基础数据是非常量,抽签程序需要做定期检查,如果数据被刷新。

:相关问题询问如何打破建立const对象,但我如果这个问题的答案意味着绝对不能对我的问题不太了解。 如果没有,我想捕捉在进一步使用一个布尔常量性。

编辑 :有人指出@DanielFrey,构造是不测试常量性的好地方。 怎么样一个const成员函数?


更新 :谢谢大家对我的修正最初病态问题,并提供答案的不同部分(建设者的界限不清常量性的rvaluedness this ,的语境意义const ,该-with hindsight-,我忽略了明显的过载绝招和const引用混叠漏洞潜伏在暗处)。 对我来说,这个问题是#1处于最佳状态。 我决定选择@ JonathanWakely的答案,因为它展示了如何定义MutableImmutable这加强了常量性的概念,以达到我想要的一个万无一失的方法类。

Answer 1:

正如其他人所指出的,如果一个物体被宣布为你不能告诉const从一个成员函数中。 你只能告诉我们,如果它被称为一个const背景下,这是不一样的。

动机:我希望能够检测一个const成员函数是否被调用const对象上,或者从非const对象的到来。 该对象可以是例如代表一个缓存和构件的视图。 如果缓存为常量,一个大概可以使用优化的抽奖程序,而如果基础数据是非常量,抽签程序需要做定期检查,如果数据被刷新。

你不能告诉可靠。

struct A
{
  void draw() { fut = std::async(&A::do_draw, this, false); }
  void draw() const { fut = std::async(&A::do_draw, this, true); }
  void update(Data&);
private:
  void do_draw(bool this_is_const) const;
  mutable std::future<void> fut;
};

A a;
const A& ca = a;
ca.draw();           // object will think it's const, but isn't
Data new_data = ...;
a.update(new_data);  // do_draw() should recheck data, but won't

你可以把它在类型系统中,通过定义不同的可变和不可变类型的建模。

struct Base
{
  virtual ~Base();
  virtual void draw() const = 0;
protected:
  void do_draw(bool) const;
};

struct MutableCache : Base
{
  virtual void draw() const { fut = std::async(&Base::do_draw, this, false); }
  void update();
};

struct ImmutableCache : Base
{
  virtual void draw() const { fut = std::async(&Base::do_draw, this, true); }
  // no update function defined, data cannot change!
};

现在,如果缓存是创建作为ImmutableCache你知道它不能改变,从而使你的替换以前的一个“常量”对象的想法。 一个MutableCache可以改变,所以需要检查刷新的数据。



Answer 2:

这是不可能的,因为构造函数(原题)

12.1的构造[class.ctor]

4.一种构造不得virtual (10.3)或static (9.4)。 构造函数可以被调用用于constvolatileconst volatile对象。 构造函数不得声明constvolatile ,或const volatile (9.3.2)。 constvolatile语义(7.1.6.1)不被应用在建的对象上。 他们时生效,在大多数派生对象的构造(1.8)结束。 构造函数不得与裁判限定符声明。

对于成员函数(当前问题),你可以简单地同时提供一个const和非const超载,都转发到一个(私人)方法,它的常量性为布尔模板参数。



Answer 3:

的类型的this (以及因此的*this )纯粹由函数的CV-限定符确定,并且取决于实际对象是否是CV-合格与否不改变。

§9.3.2 [class.this] p1

在非静态(9.3)成员函数的主体,关键字this是一个prvalue表达式,其值是用于该函数被调用的对象的地址。 的类型的this类中的成员函数XX*如果成员函数声明为const的类型, thisconst X* ,如果成员函数声明为volatile的类型, thisvolatile X* ,如果成员函数声明为const volatile的类型, thisconst volatile X*

所以,你看不到一个成员函数它的上调用的对象是否是内部 const ,但你可以根据编译器调用不同的功能const内斯:

struct X{
  void f(){ /* non-const object */ }
  void f() const{ /* const object */ }
};

int main(){
  X x1;
  X const x2;
  x1.f(); // calls non-const 'f'
  x2.f(); // calls const 'f'

  // but beware:
  X const& rx = x1;
  rx.f(); // calls const 'f', because the "object" it's invoked on is const
}

当心片段中规定的限制,虽然。



Answer 4:

什么工作?

任何方法都行不通。

运行其构造函数的对象是从来没有const 。 它可能只被分配给一个const构造已经走完之后变量。

它也不能对成员函数来确定(包括成员函数非const,因为const_cast可能已被使用)

常量性是存在于每个调用点 ,而不是函数体本身的性质的性质。

动机:我希望能够检测const对象上一个const成员函数是否被调用

你不能这样做,但你可以接近...

class C
{
public:
    void func() const
    {
        std::cout << "const!";
        func_impl();
    }
    void func()
    {
        std::cout << "non-const!";
        func_impl();
    }
private:
    void func_impl() const;
};

该对象可以是例如代表一个缓存和构件的视图。 如果缓存为常量,一个大概可以使用优化的抽奖程序,而如果基础数据是非常量,抽签程序需要做定期检查,如果数据被刷新。

这将是一个不可靠的使用const ,因为const不是对象本身的属性。 这是正在使用的对象的当前上下文的属性。

若检测到的const在目前情况下不会告诉你该对象一直在处理const上下文。



Answer 5:

我不知道是否有可能以这种方式 ,通过在构造函数中设置一个成员值的方式,但对象可以与成员函数报告其常量性:

struct Test
{
  bool is_const() const
  {
    return(true);
  }

  bool is_const()
  {
    return(false);
  }
};


Answer 6:

这是不可能的,因为有可能为一个特定的值,则可以同时观看const ,而不是const 。 考虑

MyType t = ...;
MyType& nonConstRef = t;
const MyType& constRef = t;

此时t既有const和非const引用。



Answer 7:

在对象中检测常量性是不可能的,但你的状态,你的动机是...

“我希望能够检测一个const成员函数是否被调用const对象上,或者从非const对象来了。”

嗯,这很容易,只需要提供一个非const过载。

重载可以推迟到通用的实现,例如如下:

#include <type_traits>
#include <iostream>
using namespace std;

class Test
{
private:
    template< class CvTest >
    static void print( CvTest& o )
    {
        cout << boolalpha;
        cout << "> object says: Hey, const = " << std::is_const<CvTest>::value << "!" << endl;
    }

public:
    bool print()        { return (print( *this ), false); }
    bool print() const  { return (print( *this ), true); }
};

int main()
{
    Test t;
    const Test s;

    cout << "External constness test:" << endl;
    cout << boolalpha << is_const<decltype(t)>::value << "\n";
    cout << boolalpha << is_const<decltype(s)>::value << "\n";

    cout << endl;

    cout << "Internal constness test:" << endl;
    cout << boolalpha << t.print() << "\n";
    cout << boolalpha << s.print() << "\n";
}

结果:

External constness test:
false
true

Internal constness test:
> object says: Hey, const = false!
false
> object says: Hey, const = true!
true


文章来源: Can an object know its own constness?