【问题标题】:How to express a constraint in terms of another concept如何用另一个概念来表达约束
【发布时间】:2021-12-26 11:08:15
【问题描述】:

具体描述我要解决的问题可能最容易理解。

我有一个SmartPointer 的概念,所以我可以拥有可以接受std::unique_ptrstd::shared_ptr 的函数:

template <typename T>
concept SmartPointer = requires(const T& t) {
    requires std::same_as<decltype(t.get()), typename T::pointer>;
};

我想做一个可以接受一对迭代器的函数,其中迭代器值类型必须是SmartPointer 类型,我不需要显式定义任何类型。

我可以创建一个具有 SmartPointer 约束的模板参数的函数,然后检查:

template <SmartPointer T, std::forward_iterator TIterator, std::sentinel_for<TIterator> TIteratorSentinel>
    requires std::same_as<std::iter_value_t<TIterator>, T>
void doWithSmartPointers(TIterator begin, TIteratorSentinel end) {
    for (auto it = begin; it != end; ++it) {
        // Some logic with it->get() etc.
    }
}

但是,在使用它时,我需要明确指定T,我不希望这样做:

std::vector<std::unique_ptr<int>> v{};
v.push_back(std::make_unique<int>(1));
v.push_back(std::make_unique<int>(2));
v.push_back(std::make_unique<int>(3));
doWithSmartPointer(v.begin(), v.end()); // Error, couldn't infer template argument T
doWithSmartPoint<std::unique_ptr<int>>(v.begin(), v.end()); // OK

从错误消息中,我猜我需要某种模板推导指南,但据我所知,它们只能为类/结构而不是函数定义。

我基本上想要这样的东西:

template <std::forward_iterator TIterator, std::sentinel_for<TIterator> TIteratorSentinel>
    requires std::same_as<std::iter_value_t<TIterator>, SmartPointer> // Not valid syntax!
void doWithSmartPointers(TIterator begin, TIteratorSentinel end) {
    for (auto it = begin; it != end; ++it) {
        // Some logic with it->get() etc.
    }
}

我是否以正确的方式处理这个问题?这甚至可能吗?提前谢谢!

【问题讨论】:

  • 旁白:您通常不需要在智能指针上使用get-&gt; 是递归计算的

标签: c++ c++20 c++-concepts


【解决方案1】:

您不需要T 作为模板参数:

template < std::forward_iterator TIterator
         , std::sentinel_for<TIterator> TIteratorSentinel >
    requires SmartPointer< std::iter_value_t<TIterator> >
    //       ^^^^^^^^^^^^
void whatever(TIterator begin, TIteratorSentinel end)
{
    // ...
}

【讨论】:

  • 啊,太棒了,谢谢!我认为这一定是可能的:)
【解决方案2】:

如果您有很多像whatever 这样模板化的函数,则可能值得为“指向智能指针的迭代器”定义一个概念

template <typename T>
concept SmartPointerIterator = requires std::forward_iterator<T> && SmartPointer<std::iter_value_t<T>>;

template < SmartPointerIterator TIterator
         , std::sentinel_for<TIterator> TIteratorSentinel >
void whatever(TIterator begin, TIteratorSentinel end)
{
    // ...
}

【讨论】:

    猜你喜欢
    • 2020-11-30
    • 2023-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2022-10-21
    • 1970-01-01
    相关资源
    最近更新 更多