【问题标题】:Can we use the decltype of a member function in the parameter list of another member function?我们可以在另一个成员函数的参数列表中使用一个成员函数的decltype吗?
【发布时间】:2016-03-08 17:05:31
【问题描述】:

请考虑以下代码sn-p:

template<class Tuple>
class vector
{
public:
    auto size() const noexcept(noexcept(m_elements.size())) {
        return m_elements.size();
    }

    auto operator[](decltype(size()) i)
    {
        throw_if_index_out_of_range(i);
        return m_elements[i];
    }
    auto operator[](decltype(size()) i) const
    {
        throw_if_index_out_of_range(i);
        return m_elements[i];
    }

private:
    void throw_if_index_out_of_range(decltype(size()) i) const
    {
        if (i >= size())
            throw std::length_error("element index out of range");
    }

    Tuple m_elements;
};

很遗憾,the code above won't compile with clang 3.6 (C++17)。它会产生错误消息在没有对象参数的情况下调用非静态成员函数

我们可以保留使用decltype(size()) 的想法还是我需要创建一些size_type = decltype(std::declval&lt;Tuple const&amp;&gt;().size())

【问题讨论】:

  • 为什么不直接使用std::size_t,因为它保证足够大以包含任何对象的字节大小。
  • @NathanOliver 原因 Tuple 可能会使用您不知道的某种“大小”。 “索引”可能是一个复杂的对象。
  • @NathanOliver 此外,在其他情况下可能会出现相同的问题。我主要对问题的技术方面感兴趣。
  • 没问题。我从未见过将非整数类型用作索引,但没有什么能阻止任何人这样做。
  • 即使decltype(size) 被允许,声明一个 typedef 会让事情更清楚。 using size_type = ..;

标签: c++ c++14 decltype c++17 return-type-deduction


【解决方案1】:

只有在有限的范围内this 是一个有效的表达式,在您的情况下它以right after you need it 开头。您可以引入一个对象(各种)以确保对size 的调用有效,扮演隐式this-&gt; 的角色:

auto operator[](decltype( std::declval<vector&>().size() ) i);

话虽如此,我会反对它——即使你可以访问this,我也会反对它。该声明显然难以阅读和理解,根本没有任何好处。特别是考虑到您在const-qualified 重载中也重复了decltype( … ),其结果是审阅者必须仔细解析那里正在测试的表达式并回溯到 previous 重载检查表达式中存在哪些差异(如果有)。

不要重复自己,重构:

using size_type = …; // choose one spec and stick to it

auto operator[](size_type i);
auto operator[](size_type i) const;

size_type 也不必是公共接口的一部分,我们只关心避免重复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-10
    • 2022-01-10
    • 2016-09-11
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多