【发布时间】:2015-01-20 21:02:08
【问题描述】:
有没有办法定义一个可以从“const”和“non-const”对象访问的成员函数?
我的sList 实现列表类需要这个。在其中,我想声明一个函数,该函数将另一个函数作为参数,该函数具有指向sList 的“const”或“non-const”指针,并将为当前sList 结构中的每个列表调用它。
这是它的声明:
template <typename T>
struct sList
{
sList(initializer_list<T>);
inline void DoForEachList(auto pFunc)
{
for(auto p = this; p; p = p->pNext)
pFunc(p);
}
~sList();
T dat;
sList *pNext = nullptr;
};
我使用 auto pFunc 是因为我最终也想通过 lambda。所以现在,如果我有一个这种类型的 const 对象并从中调用“DoForEachList”作为参数 lambda 函数传递,其中 1 个 arg 来自“auto”类型。我的编译器将失败,如下所示:
错误:将
const sList<unsigned char>作为this参数传递给void sList<T>::DoForEachList(auto:1)[withauto:1=main()::<lambda(sList<unsigned char>*)>;T=unsigned char]' 丢弃限定符 [-fpermissive]
以及调用DoForEachList的代码:
void main()
{
extern const sList<unsigned char> cvobj;
cvobj.DoForEachList([] (auto pCurr) {/* Do something */});
}
有什么方法可以像这样定义DoForEachList 成员函数(或成员函数的模板):
template <typename T>
struct sList
{
inline void DoForEachList(auto pFunc) auto //either 'const' or none
{
for(auto p = this; p; p = pNext->pNext)
pFunc(p);
}
//...
};
【问题讨论】:
-
您可以使用友元函数模板,也可以使用两个成员函数包装器。
-
非常简单 - 非常量对象始终可以绑定到
const引用,但反之则不行。这是一个隐式转换(限定转换)。嗯。但是,如果您在非常量对象上调用它时确实想修改该对象,那将毫无用处。在这种情况下,只需编写两个函数即可。 -
同一个身体——呃,这是最好的方法吗?使用包装函数不是一个解决方案,因为这样会错误地推断出 'pFunc' 参数(如果我们使用 const_cast 为 'this' 在 'const' 成员函数中包装 'non-const' 调用,则 lambda 函数 arg 将被推断为 ' sList *' 这是错误的)。
-
如果我们以相反的方式包装(在'non-const'成员函数中调用'const'),也会发生同样的情况。这样 lambda 函数 arg 将被推导出为 'const sList *'。
-
我喜欢 dyp 的解决方案。请记住,
friend函数不是成员函数,也没有this。相反,它将是从两个成员函数包装器传递的普通旧参数。你不需要const_cast。朋友模板的实例之一将具有const-qualified 类型参数。另一个实例不会。它们都是 const 正确的。
标签: c++ c++11 gcc c++14 mingw-w64