【问题标题】:How to use trailing return type with a templated class member如何将尾随返回类型与模板类成员一起使用
【发布时间】:2013-12-10 01:45:38
【问题描述】:

我正在尝试实现以下类:

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 > >'

我认为可能与模板类型的多阶段传递有关,因此将其更改为decltype(this-&gt;m_container.rbegin()),但这也不起作用。

我怎样才能让它工作?

示例 - http://ideone.com/ekVYlH

【问题讨论】:

  • 嗯,请稍等一下 decltype(auto),不要打扰^^。
  • 您是否尝试过使用std::declval 而不是直接在decltype 表达式中使用成员?那应该解决它。不是答案,因为我不知道这是标准要求还是您的工具链存在问题
  • beginend 需要知道m_container,需要在他们之前声明。

标签: c++ c++11 trailing-return-type


【解决方案1】:

函数的 trailing-return-type 是其“签名”(声明)的一部分,而不是其“主体”(定义)的一部分,因此,它只会看到之前声明过的名称

在您声明 begin 成员函数时,m_container 尚未声明。 (请注意,该问题并非特定于模板类。)

  • 您可以在类定义中将m_container 的声明上移(但它会强制您将私有成员放在公共接口之前,这与通常做法相反...)。

    李>
  • 您可以使用declval 变通:将m_container 替换为std::declval&lt;Container&amp;&gt;() 内的std::declval&lt;Container&amp;&gt;()http://ideone.com/aQ8Apa

(正如 cmets 中所说,在 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) 违反)。

【讨论】:

  • 太好了,谢谢。我选择了std::declval&lt;Container&amp;&gt;() 作为解决方案,因为我讨厌在公共或受保护的成员/方法之前拥有私有类成员/方法。
【解决方案2】:

名称m_container 尚未在函数被声明时引入。切换声明顺序,代码就行了。

查看工作版本here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-16
    • 1970-01-01
    • 1970-01-01
    • 2014-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多