代理对象的常量正确性
Const-correctness with proxy object
我对以下代码感到困惑,其中 class Baz
允许通过代理访问其内部数据 class Bar
:
struct Foo{};
template<class T>
struct Bar
{
Bar(T &val_): val(val_) {}
T &val;
};
struct Baz
{
Bar<const Foo> get() const {return Bar<const Foo>(foo);}
Bar<Foo> get() {return Bar<Foo> (foo);}
Foo foo;
};
struct FooBaz
{
FooBaz(Baz &baz_): baz(baz_) {}
// Bar<const Foo> get() const {return baz.get();} // this do not compile
Bar<const Foo> get() const {return const_cast<const Baz &>(baz).get();} // the const_cast seems to be required
Baz &baz;
};
看来我必须做一个const_cast
来调度到右边的Baz::get()
函数。
我不明白的第一件事是,如果 FooBaz::baz
是普通的 Baz
而不是引用,它会起作用:
struct Foo{};
template<class T>
struct Bar
{
Bar(T &val_): val(val_) {}
T &val;
};
struct Baz
{
Bar<const Foo> get() const {return Bar<const Foo>(foo);}
Bar<Foo> get() {return Bar<Foo> (foo);}
Foo foo;
};
struct FooBaz
{
FooBaz(Baz &baz_): baz(baz_) {}
Bar<const Foo> get() const {return baz.get();} // Ok
Baz baz;
};
我对 const 函数成员的理解是它使 this
指针指向 const,但实际上我并不完全清楚这意味着什么......做所有的数据成员是 'as if they are const'?有明确的参考吗?
另一个有趣的事情是,如果我使用 std::reference_wrapper
作为代理 class,那么它可以在没有 const_cast
:
的情况下工作
#include <functional>
struct Foo {};
struct Baz
{
std::reference_wrapper<const Foo> get() const {return std::cref(foo);}
std::reference_wrapper<Foo> get() {return std::ref (foo);}
Foo foo;
};
struct FooBaz
{
FooBaz(Baz &baz_): baz(baz_) {}
std::reference_wrapper<const Foo> get() const {return baz.get();} // Ok
Baz &baz;
};
std::reference_wrapper
有什么魔力?
谢谢!
it works if the FooBaz::baz
is a plain Baz
and not a reference:
这就是重点。在 const
成员函数中,数据成员也被视为 const
。请注意,对于引用,这意味着引用成员本身被视为 const
,而不是被引用的对象。即 baz
将被视为 Baz & const
(const 引用)而不是 Baz const &
(对 const 的引用)。事实上,引用不能是 const 限定的,并且 const-ness 只是被忽略,因为效果,即使在 const
成员函数中,baz.get();
也将始终调用非 const Baz::get()
.
std::reference_wrapper
版本没有变化,baz.get();
仍然调用非常量 Baz::get()
和 returns std::reference_wrapper<Foo>
。 std::reference_wrapper
有一个 converting constructor,返回的 std::reference_wrapper<Foo>
可以转换为 std::reference_wrapper<const Foo>
,它存储对从 std::reference_wrapper<Foo>
获得的对象的引用(通过
conversion operator).
I must do a const_cast
to dispatch to the right Baz::get()
function.
是的。或 std::as_const
,或使 Bar<T>
可转换为 Bar<const T>
。
What I understand about a const function member is that it makes the this pointer-to-const, but in fact it is not totally clear to me what it means... Do all the data member be 'as if they are const'?
是的,成员的行为就像 const
。
The expression E1->E2
is exactly equivalent to (*E1).E2
for built-in types; that is why the following rules address only E1.E2
.
In the expression E1.E2
:
if E2
is a non-static data member:
if E2
is of reference type T&
or T&&
, the result is an lvalue of type T
designating the object or function to which E2 refers,
otherwise, if E1
is an lvalue, the result is an lvalue designating that non-static data member of E1
,
otherwise (if E1
is an xvalue (which may be materialized from prvalue)), the result is an xvalue designating that non-static data member of E1
.
If E2
is not a mutable member, the cv-qualification of the result is the union of the cv-qualifications of E1
and E2
, otherwise (if E2
is a mutable member), it is the union of the volatile-qualifications
of E1
and E2
;
当通过指向 const
class 的指针访问时,其成员变为 const
.
但是常量只在顶层添加。如果通过指向 const
的指针访问 int *member;
,它将变为 int *const member;
,而不是 const int *const member;
。
引用以类似的方式工作,但由于引用本身不能是 const
1,因此它们的类型没有改变。
if I use a std::reference_wrapper
as proxy class, then it works without the const_cast
那是因为它有一个允许从 std::reference_wrapper<T>
.
构造 std::reference_wrapper<const T>
的构造函数
1 是的,引用在创建后不能更改为指向不同的对象,但形式上它不是 const
。 std::is_const
returns false
供参考。
我对以下代码感到困惑,其中 class Baz
允许通过代理访问其内部数据 class Bar
:
struct Foo{};
template<class T>
struct Bar
{
Bar(T &val_): val(val_) {}
T &val;
};
struct Baz
{
Bar<const Foo> get() const {return Bar<const Foo>(foo);}
Bar<Foo> get() {return Bar<Foo> (foo);}
Foo foo;
};
struct FooBaz
{
FooBaz(Baz &baz_): baz(baz_) {}
// Bar<const Foo> get() const {return baz.get();} // this do not compile
Bar<const Foo> get() const {return const_cast<const Baz &>(baz).get();} // the const_cast seems to be required
Baz &baz;
};
看来我必须做一个const_cast
来调度到右边的Baz::get()
函数。
我不明白的第一件事是,如果 FooBaz::baz
是普通的 Baz
而不是引用,它会起作用:
struct Foo{};
template<class T>
struct Bar
{
Bar(T &val_): val(val_) {}
T &val;
};
struct Baz
{
Bar<const Foo> get() const {return Bar<const Foo>(foo);}
Bar<Foo> get() {return Bar<Foo> (foo);}
Foo foo;
};
struct FooBaz
{
FooBaz(Baz &baz_): baz(baz_) {}
Bar<const Foo> get() const {return baz.get();} // Ok
Baz baz;
};
我对 const 函数成员的理解是它使 this
指针指向 const,但实际上我并不完全清楚这意味着什么......做所有的数据成员是 'as if they are const'?有明确的参考吗?
另一个有趣的事情是,如果我使用 std::reference_wrapper
作为代理 class,那么它可以在没有 const_cast
:
#include <functional>
struct Foo {};
struct Baz
{
std::reference_wrapper<const Foo> get() const {return std::cref(foo);}
std::reference_wrapper<Foo> get() {return std::ref (foo);}
Foo foo;
};
struct FooBaz
{
FooBaz(Baz &baz_): baz(baz_) {}
std::reference_wrapper<const Foo> get() const {return baz.get();} // Ok
Baz &baz;
};
std::reference_wrapper
有什么魔力?
谢谢!
it works if the
FooBaz::baz
is a plainBaz
and not a reference:
这就是重点。在 const
成员函数中,数据成员也被视为 const
。请注意,对于引用,这意味着引用成员本身被视为 const
,而不是被引用的对象。即 baz
将被视为 Baz & const
(const 引用)而不是 Baz const &
(对 const 的引用)。事实上,引用不能是 const 限定的,并且 const-ness 只是被忽略,因为效果,即使在 const
成员函数中,baz.get();
也将始终调用非 const Baz::get()
.
std::reference_wrapper
版本没有变化,baz.get();
仍然调用非常量 Baz::get()
和 returns std::reference_wrapper<Foo>
。 std::reference_wrapper
有一个 converting constructor,返回的 std::reference_wrapper<Foo>
可以转换为 std::reference_wrapper<const Foo>
,它存储对从 std::reference_wrapper<Foo>
获得的对象的引用(通过
conversion operator).
I must do a
const_cast
to dispatch to the rightBaz::get()
function.
是的。或 std::as_const
,或使 Bar<T>
可转换为 Bar<const T>
。
What I understand about a const function member is that it makes the this pointer-to-const, but in fact it is not totally clear to me what it means... Do all the data member be 'as if they are const'?
是的,成员的行为就像 const
。
The expression
E1->E2
is exactly equivalent to(*E1).E2
for built-in types; that is why the following rules address onlyE1.E2
.In the expression
E1.E2
:
if
E2
is a non-static data member:if
E2
is of reference typeT&
orT&&
, the result is an lvalue of typeT
designating the object or function to which E2 refers, otherwise, ifE1
is an lvalue, the result is an lvalue designating that non-static data member ofE1
, otherwise (ifE1
is an xvalue (which may be materialized from prvalue)), the result is an xvalue designating that non-static data member ofE1
.If
E2
is not a mutable member, the cv-qualification of the result is the union of the cv-qualifications ofE1
andE2
, otherwise (ifE2
is a mutable member), it is the union of the volatile-qualifications ofE1
andE2
;
当通过指向 const
class 的指针访问时,其成员变为 const
.
但是常量只在顶层添加。如果通过指向 const
的指针访问 int *member;
,它将变为 int *const member;
,而不是 const int *const member;
。
引用以类似的方式工作,但由于引用本身不能是 const
1,因此它们的类型没有改变。
if I use a
std::reference_wrapper
as proxy class, then it works without theconst_cast
那是因为它有一个允许从 std::reference_wrapper<T>
.
std::reference_wrapper<const T>
的构造函数
1 是的,引用在创建后不能更改为指向不同的对象,但形式上它不是 const
。 std::is_const
returns false
供参考。