I have a class MyVariable
that holds an object and does some extra work when this object has to be modified. Now I want to specialize this to MyContainer
for container objects that perform this extra work only when the container itself is modified (eg via push_back()
) but not its elements.
My code looks like this:
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;
}
However, with GCC4.7.2 I get an error that I cannot access _element
because it is protected.
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
What's going on here?
The problem does seem to be specific to the use of decltype()
- if I explicitly declare nonconst_at()
to return T::value_type&
, thus:
template<typename Arg>
typename T::value_type& nonconst_at(Arg&& arg)
then GCC 4.8.2 compiles it with no warnings or errors. That's fine for standard containers, but obviously doesn't help every situation.
Actually calling this->_element.at(arg)
isn't a problem: I can omit the trailing return type and have the compiler infer it:
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));
}
with just a warning (which disappears with -std=c++1y
) and no errors. I still need the this->
, because _element is a member of a dependent base class (thanks, Simple ).
As you're only interested in the type of the return value of T::at()
, you can use the decltype
of calling it with any T you like, even a null pointer:
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));
}
It's ugly, but it does seem to work.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.