C++:派生类无法访问受保护的成员

4

我有一个类MyVariable,它保存一个对象并在修改该对象时执行一些额外的工作。现在我想将其专门化为MyContainer,用于容器对象,仅在修改容器本身时执行此额外的工作(例如通过push_back()),而不是其元素。

我的代码看起来像这样:

template<typename T>
class MyVariable
{
public:
    //read-only access if fine
    const T* operator->() const {return(&this->_element);}
    const T& operator*()  const {return( this->_element);}

    //write acces via this function
    T& nonconst()
    {
        //...here is some more work intended...
        return(this->_element);
    }
protected:
    T _element;
};


template<typename T>
class MyContainer: public MyVariable<T>
{
public:
    template<typename Arg>
    auto nonconst_at(Arg&& arg) -> decltype(MyVariable<T>::_element.at(arg))
    {
        //here I want to avoid the work from MyVariable<T>::nonconst()
        return(this->_element.at(arg));   
    }
};


#include <vector>
int main()
{
    MyContainer<std::vector<float>> container;
    container.nonconst()={1,3,5,7};
    container.nonconst_at(1)=65;
}

然而,使用GCC4.7.2时,我会收到一个错误,因为我无法访问_element,因为它是受保护的。
test1.cpp: In substitution of 'template<class Arg> decltype (MyVariable<T>::_element.at(arg)) MyContainer::nonconst_at(Arg&&) [with Arg = Arg; T = std::vector<float>] [with Arg = int]':
test1.cpp:39:25:   required from here
test1.cpp:17:4: error: 'std::vector<float> MyVariable<std::vector<float> >::_element' is protected
test1.cpp:26:7: error: within this context
test1.cpp: In member function 'decltype (MyVariable<T>::_element.at(arg)) MyContainer<T>::nonconst_at(Arg&&) [with Arg = int; T = std::vector<float>; decltype (MyVariable<T>::_element.at(arg)) = float&]':
test1.cpp:17:4: error: 'std::vector<float> MyVariable<std::vector<float> >::_element' is protected
test1.cpp:39:25: error: within this context
test1.cpp: In instantiation of 'decltype (MyVariable<T>::_element.at(arg)) MyContainer<T>::nonconst_at(Arg&&) [with Arg = int; T = std::vector<float>; decltype (MyVariable<T>::_element.at(arg)) = float&]':
test1.cpp:39:25:   required from here
test1.cpp:17:4: error: 'std::vector<float> MyVariable<std::vector<float> >::_element' is protected
test1.cpp:26:7: error: within this context

这里发生了什么?

2
看起来像是编译器的错误。在 https://ideone.com/KMi5OK 上,你的代码可以编译。 - Serge Rogatch
gcc5.2.0 上也可以正常运行,但在 visual studio 2015 上会出错,因此确实是编译器的问题! - vishal
CLion:编译正常。 - Naman
@nullpointer:IDE 是无关紧要的。 - Karoly Horvath
1个回答

3
问题似乎只与使用decltype()有关 - 如果我显式声明nonconst_at()返回T::value_type&,则如下所示:
template<typename Arg>
typename T::value_type& nonconst_at(Arg&& arg)

然后,GCC 4.8.2 编译它时没有警告或错误。这对于标准容器来说很好,但显然并不能适用于每种情况。

实际上调用 this->_element.at(arg) 并不是问题:我可以省略尾随返回类型并让编译器推断它:

template<typename Arg>
auto& nonconst_at(Arg&& arg)
{
    //here I want to avoid the work from MyVariable<T>::nonconst()
    return this->_element.at(std::forward<Arg>(arg));
}

只有一个警告(使用-std=c++1y后消失),没有错误。但我仍需要 this->,因为_element是依赖基类的成员(感谢Simple)。

编辑-额外解决方法:

由于你只关心 T::at() 返回值的类型,你可以使用任何你喜欢的T来调用它的 decltype,甚至是空指针:

template<typename Arg>
auto nonconst_at(Arg&& arg) -> decltype(((T*)nullptr)->at(arg))
{
    //here I want to avoid the work from MyVariable<T>::nonconst()
    return this->_element.at(std::forward<Arg>(arg));
}

虽然看起来不美观,但它似乎确实有效。


1
你必须写this->_element,因为_element是一个依赖基类的成员。 - Simple

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接