如何初始化指向模板化祖先数据的指针
How init pointer to data of templated ancestor
只是一个示例代码:
template <class T> class TempBase
{
protected:
string m_str;
};
template <class T> class Temp: public TempBase<T>
{
public:
void method()
{
string
&s = TempBase<T>::m_str //reference works fine
/*NOTE compile failed:
error: ‘std::string TempBase<int>::m_str’ is protected
error: within this context
error: cannot convert ‘std::string TempBase<int>::* {aka std::basic_string<char> TempBase<int>::*}’ to ‘std::string* {aka std::basic_string<char>*}’ in initialization
*/
, *ps = &TempBase<T>::m_str
, *ps2 = &m_str //compile failed, obviously: ‘m_str’ was not declared in this scope
, *ps3 = &s //this is workaround, works fine
;
}
};
void f()
{
Temp<int> t;
t.method();
}
目标: 具有祖先成员 TempBase<T>::m_str
的 std::string *
类型的 init 指针。
问题:语法正确未知
注释:以前的代码包含 2 个故意编译错误:
- 尝试将成员指针转换为数据指针
- 模板化祖先成员必须完全合格
和 1 个解决方法。
问题:在这种情况下,获取指向祖先数据的指针的正确语法是什么?
我将假设您想要的行为最好通过解决方法来描述
&s = TempBase<T>::m_str;
(您在问题中提供)而不是解决方法
&s = this->m_str;
这在您的示例中也有效。
解决方案:&(温度基准::m_str)
原因:TempBase::m_str是限定 ID,(TempBase::m_str) 不是。
代码示例:
#include <iostream>
#include <string>
using namespace std;
template <class T> class TempBase
{
protected:
string m_str;
};
template <class T> class Temp: public TempBase<T>
{
public:
void method()
{
string* ps3 = &(TempBase<T>::m_str); //this is workaround, works fine
(*ps3) += "ciao";
cout << *ps3 << endl;
}
};
void f()
{
Temp<int> t;
t.method();
}
int main( int argc, char* argv[] )
{
f();
}
你可以在这里尝试
&m_str
不起作用的原因:[temp.dep]/3
在类或类模板的定义中,如果基类依赖于模板参数,则在非限定名称查找期间不会检查基类范围 [...]
但是,this->m_str
表示从属名称(因为根据 [temp.dep.expr]/2 this
从属名称)。在这种情况下,使用依赖名称查找来查找基类成员。
如果我们在类范围之外添加模板的专用化和名称,问题会更加明显:
string m_str;
template<class T> struct A { string m_str; };
template<> struct A<int> { /* no member */ };
template<class T> struct B : A
{
void foo() { m_str = "hello"; }
};
B<int>().foo(); // clearly modifies the global `m_str`
B<double>().foo(); // modifies what?
如果搜索基类范围,则在实例化之前(在模板参数已知之前)不知道m_str
引用的内容。此外,这很容易导致意外结果。
因此,不会搜索基类范围(如果基类是依赖的,并且我们处于"模板上下文"中)。
&s = TempBase<T>::m_str
工作的原因:
id-expression TempBase<T>::m_str
使用的是限定 id,因此搜索TempBase<T>
的范围并找到成员m_str
。
&TempBase<T>::m_str
不起作用但&(TempBase<T>::m_str)
起作用的原因:[expr.unary.op]/3
一元
&
运算符的结果是指向其操作数的指针。操作数应为左值或限定 ID。如果操作数是一个限定 id,命名某个类C
m
T
类型的非静态成员,则结果的类型为"指向类型T
的类C
的成员的指针",并且是指定C::m
的 prvalue 。否则,如果类型 表达式T
,结果的类型为"指向T
的指针",并且是一个 prvalue 作为指定对象的地址 (1.7) 或指向指定函数的指针。
参数化表达式 (TempBase<T>::m_str)
不是限定 id,因此&(TempBase<T>::m_str)
不构成指向成员的指针,而是指向 (TempBase<T>::m_str)
表示的对象的普通指针。
- 防止主数据类型C++的隐式转换
- 用于访问容器<T>数据成员的正确 API
- 嵌套在类中时无法设置成员数据
- 使用流处理接收到的数据
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 在cuda线程之间共享大量常量数据
- C++将文本文件中的数据读取到结构数组中
- 如何在C++中序列化结构数据
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 在c代码之间共享数据的最佳方式
- 链表,反向函数,数据结构
- 数据成员SFINAE的C++17测试:gcc vs clang
- C++浮点数据类型和字符串数据类型无法子到模板函数中
- 如何对点云数据进行排序
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 尝试通过OCI例程从Oracle获取blob数据,但出现错误:ORA-01008:并非所有变量都绑定
- Cuda C++:设备上的Malloc类,并用来自主机的数据填充它
- 如何初始化指向模板化祖先数据的指针