与decltype
和std::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的答案,因为它展示了如何定义Mutable
和Immutable
这加强了常量性的概念,以达到我想要的一个万无一失的方法类。
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)。 构造函数可以被调用用于const
, volatile
或const volatile
对象。 构造函数不得声明const
, volatile
,或const volatile
(9.3.2)。 const
和volatile
语义(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
类中的成员函数X
是X*
。 如果成员函数声明为const
的类型, this
是const X*
,如果成员函数声明为volatile
的类型, this
是volatile X*
,如果成员函数声明为const volatile
的类型, this
是const 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?