我正在尝试实现以下类:
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;
};
我使用尾随返回类型的原因是因为我不知道m_container是否为const,所以我让编译器为我工作。但是,我收到以下编译器错误:
/Users/mark/Blah/Stdx.h:77:40:没有名为'm_container'的成员 'stdx :: reverse_adaptor&gt; &GT;'
我认为它可能与模板化类型的多阶段传递有关,因此将其更改为读取decltype(this->m_container.rbegin())
,但这也不起作用。
我怎样才能让它发挥作用?
答案 0 :(得分:10)
函数的 trailing-return-type 是其“签名”(声明)的一部分,而不是其“body”(定义)的一部分,因此,它只能看到之前声明的名称。。
在您声明begin
成员函数时,尚未声明m_container
。 (请注意,该问题并非特定于模板类。)
您可以在类定义中移动m_container
的声明(但它会强制您将私有成员放在公共接口之前,这与常规做法相反......)。
您可以使用declval
进行解决:将m_container
替换为std::declval<Container&>()
内的decltype
:http://ideone.com/aQ8Apa
(如评论中所述,在C ++ 14中,您将能够删除尾随返回类型,并使用decltype(auto)
作为“正常”返回类型。)
附录:至于为什么你可以在成员函数的类内体中使用尚未声明的成员而不是在尾随返回类型中,这是因为以下内容:
class Foo {
public:
auto data() const -> decltype(m_data)
{
return m_data;
}
private:
SomeType m_data;
};
[免责声明:非正式措辞!] 将“由编译器重写”的内容变成与此相当的东西:
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;
}
其中名称在声明之前不能使用(第一个decltype(m_data)
违反了该名称。)
答案 1 :(得分:2)
在声明的函数时,尚未引入名称m_container
。切换声明的顺序,代码将起作用。
查看工作版here。