I'm trying to implement the following class:
template <typename Container>
class reverse_adaptor
{
public: // Construction
reverse_adaptor(Container &container) :
m_container(container)
{}
public: // STL container static polymorphism
auto begin() const -> decltype(m_container.rbegin())
{
return m_container.rbegin();
}
auto end() const -> decltype(m_container.rend())
{
return m_container.rend();
}
private: // Members
Container &m_container;
};
The reason I'm using the trailing return type is because I don't know if m_container will be const or not, so I let the compiler work it out for me. However, I'm getting the following compiler errors:
/Users/mark/Blah/Stdx.h:77:40: No member named 'm_container' in 'stdx::reverse_adaptor > >'
I thought it might be related to the multi-stage pass of templated types, so changed it to read decltype(this->m_container.rbegin())
, but that didn't work either.
How can I get this to work?
Example - http://ideone.com/ekVYlH
The trailing-return-type of a function is part of its “signature” (declaration), not of its “body” (definition), and as such, it only sees names that were declared before.
At the point where you declare your
begin
member function,m_container
hasn't been declared yet. (Note that the issue is not specific to template classes.)You could move the declaration of
m_container
up in the class definition (but it forces you to put private members before public interface, which is contrary to common practice...).You can work-around with
declval
: replacem_container
withstd::declval<Container&>()
inside thedecltype
: http://ideone.com/aQ8Apa(As said in the comments, in C++14 you'll be able to drop the trailing return type and just use
decltype(auto)
as the “normal” return type.)Addendum: As for why you can use not-yet-declared members inside the in-class body of a member function but not in the trailing return type, it's because the following:
will be [disclaimer: informal wording!] kind of “rewritten by the compiler” into something equivalent to this:
where a name cannot be used before its declaration (which the first
decltype(m_data)
violates).