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:
class Foo {
public:
auto data() const -> decltype(m_data)
{
return m_data;
}
private:
SomeType m_data;
};
will be [disclaimer: informal wording!] kind of “rewritten by the compiler” into something equivalent to this:
class Foo {
public:
inline auto data() const -> decltype(m_data); // declaration only
private:
SomeType m_data;
};
// at this point, all members have been declared
inline auto Foo::data() const -> decltype(m_data) // definition
{
return m_data;
}
where a name cannot be used before its declaration (which the first decltype(m_data)
violates).