【问题标题】:Why does the std::sentinel_for concept require default constructability?为什么 std::sentinel_for 概念需要默认可构造性?
【发布时间】:2020-07-16 19:39:54
【问题描述】:

为什么新的std::sentinel_for 概念要求标记类型为default_initializable(通过semiregular)?这不排除了一大类有用的哨兵类型,其中默认构造没有任何意义?

例子:

//Iterate over a string until given character or '\0' is found
class char_sentinel
{
public:
    char_sentinel(char end) :
        end_character(end)
    { }

   friend bool operator==(const char* lhs, char_sentinel rhs)
   {
       return (*lhs == '\0') || (*lhs == rhs.end_character);
   }

   friend bool operator!=(const char* lhs, char_sentinel rhs) { ... }
   friend bool operator==(char_sentinel lhs, const char* rhs) { ... }
   friend bool operator!=(char_sentinel lhs, const char* rhs) { ... }

private:
    char end_character; 
};

我知道我可以添加一个初始化为 '\0' 的默认构造函数,但如果我认为这是对结构的滥用并想阻止它呢?

【问题讨论】:

  • 重复链接中的解释仅将问题转移到“为什么不是所有迭代器都需要默认构造?”。为什么输入迭代器也不需要是默认可构造的?
  • 我们也有人在 cpplang Slack 上提问,我不知道答案。关于ostream_iterator 的链接问题(它是一个迭代器而不是哨兵,并且它本身也不是哨兵因为 it isn't default-constructible)根本不是这个问题的重复。跨度>
  • @Quuxplusone 更重要的是,它也不是哨兵,因为它没有(而且从来没有,与默认构造函数不同)相等。但是“为什么输出迭代器需要默认可构造”这个问题实际上与“为什么哨兵需要默认可构造”非常相似,并且具有相同的答案(除了我们删除了之前的限制)。

标签: c++ language-lawyer c++20 c++-standard-library c++-concepts


【解决方案1】:

虽然这不是 this question 的严格重复,但我的回答在很大程度上仍然适用。

关于类型行为方式的 Elements of Programming 设计理念是它们应该是regular,EoP 定义为:

T的计算基础包括相等、赋值、析构函数、默认构造函数、复制构造函数、全序(或默认全序)和底层类型

我认为随着时间的推移,这个定义已被证明不是最有用的定义。许多算法不需要相等,因此semiregular。但在许多情况下,即使是默认构造也不是必需的。

虽然我们从 P2325R3 中的输入迭代器、输出迭代器和视图中删除了默认构造要求,但该论文没有涉及(甚至讨论)标记。哨兵的论点在很大程度上是相同的——它不是一个重要的要求,算法也不需要它——但我们只是没有追求将sentinel_for从需要semiregular弱化为只需要copyable。我不确定我们是否有充分的理由避免这样做,除了不值得这样做,因为无论如何编写哨兵的频率都低于迭代器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 2019-03-01
    • 1970-01-01
    • 2019-09-28
    • 2018-10-04
    相关资源
    最近更新 更多