允许在包装模板中将非常数转换为常量
Allow a non-const to convert to const in a wrapper template
如何允许非常量引用在包装模板复制构造函数中转换为常量引用?请注意,我的复制构造函数是一个逻辑移动构造函数(C++11之前)——init
成员跟踪当前有效的包装器。
template<typename T>
class wrap
{
T & object;
bool init;
public:
wrap( T& object ) : object(object), init( true ) { }
//attempt which fails since "init" is private in other type
template<typename O>
wrap( wrap<O> const & o )
: object( o.object )
, init( true )
{
const_cast<wrap<O>&>(o).init = false;
}
};
如果另一个类型完全相同,这也可以正常工作,因为访问规则允许访问私有init
变量。基本上,以下内容应该有效:
//adding const
wrap<Type> a( get() );
wrap<Type const> b = a;
//base type would also be nice
wrap<BaseType> c = a;
Befriend其他专业:
template <typename U> friend class wrap;
或者为了更好的封装,只需要它们的转换构造函数:
template <typename U> template <typename O>
friend wrap<U>::wrap(wrap<O> const &);
最好声明init
mutable
;使用const_cast
,如果有人试图复制const
对象,则存在未定义行为的风险。
此外,请注意,构造函数模板不会重载隐式生成的复制构造函数。您还需要一个复制构造函数来对init
:执行正确的操作
wrap(wrap const & o) : object(o.object), init(true) {o.init = false;}
为了绕过访问限制,您可以简单地将wrap
的其他实例添加为好友,因此在类的某个位置添加template<typename U> friend class wrap;
。这样你的例子就可以编译了。
然而,你真的不应该那样对编译器撒谎。您将o
作为const ref
传递,并承诺不更改它,然后再更改它。这是不好的(或者标准允许的),所以编译器可以自由地以各种方式破坏代码。您确实应该使用const_cast
来调用函数,这些函数将参数视为非常量,但不会更改参数本身(想到c api)。在这种情况下,我建议将构造函数声明为template<typename O> wrap(wrap<O>& o)
。如果你真的想把它作为常量引用,你也可以把init
声明为mutable
,这意味着即使对象是const
,它也可以被修改
您还应该注意,您没有声明复制构造函数(即使template<typename O> wrap( wrap<O> const & o )
可以接受wrap<T>
,它也不算在内,所以您也需要定义它,或者复制到同一类型将使用编译器生成的复制构造函数。
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 将非常大的 int 转换为双倍,在某些计算机上会损失精度
- 转换非常长的字符串文本C++以满足最大行长策略
- 在 C/C++ 中将非常大的 int(写为字符串)转换为二进制字符串
- 错误:在非常简单的示例中,预期的构造函数、析构函数或类型转换
- 一个非常弱的引用(无法转换为共享)
- 在非常简单的代码上从“char”到“char*”的转换无效
- 将十进制转换为二进制,并计算其中的数字非常非常大
- Base2 到 Base10 转换器不适用于非常大的数字?