You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Concepts约束std::input_iterator的值类型为bar?

用C++ Concepts约束迭代器指向bar类型

问题描述

现有如下C++代码:

#include <iterator>
#include <vector>
struct bar{};
struct details {};
struct foo {
    details det;
    std::vector<bar> data;
};

template <std::input_iterator Iter>
foo create_foo(const details& details, Iter begin, Iter end) {
    return foo {
        .det = details,
        .data = {begin, end}
    };
}

int main() {
    std::vector<bar> bars = {bar{},bar{},bar{}};
    create_foo({}, bars.begin(), bars.end());
    return 0;
}

需求:foo::data是bar类型的容器,其构造函数接受两个迭代器。需要将输入迭代器约束为仅指向bar类型元素的迭代器(如std::vector<bar>::iterator或std::list<bar>::iterator),询问如何通过C++20 Concepts实现该约束。

解决方案

方法1:自定义Concept约束

先定义一个Concept,同时满足两个条件:迭代器是std::input_iterator,且其指向的元素类型为bar:

#include <iterator>
#include <vector>
#include <list>
#include <concepts>

struct bar{};
struct details {};
struct foo {
    details det;
    std::vector<bar> data;
};

// 自定义Concept:指向bar的输入迭代器
template <typename Iter>
concept BarInputIterator = std::input_iterator<Iter> &&
                           std::same_as<typename std::iterator_traits<Iter>::value_type, bar>;

// 使用Concept约束模板参数
template <BarInputIterator Iter>
foo create_foo(const details& details, Iter begin, Iter end) {
    return foo {
        .det = details,
        .data = {begin, end}
    };
}

int main() {
    std::vector<bar> bars = {bar{},bar{},bar{}};
    create_foo({}, bars.begin(), bars.end()); // 合法,符合约束

    std::list<bar> bar_list = {bar{}, bar{}};
    create_foo({}, bar_list.begin(), bar_list.end()); // 合法,符合约束

    // std::vector<int> ints = {1,2,3};
    // create_foo({}, ints.begin(), ints.end()); // 编译错误:违反Concept约束
    return 0;
}

方法2:内嵌约束(无需自定义Concept)

如果不需要复用这个约束,可以直接在模板参数后通过requires子句添加条件:

#include <iterator>
#include <vector>
#include <concepts>

struct bar{};
struct details {};
struct foo {
    details det;
    std::vector<bar> data;
};

template <std::input_iterator Iter>
requires std::same_as<typename std::iterator_traits<Iter>::value_type, bar>
foo create_foo(const details& details, Iter begin, Iter end) {
    return foo {
        .det = details,
        .data = {begin, end}
    };
}

int main() {
    std::vector<bar> bars = {bar{},bar{},bar{}};
    create_foo({}, bars.begin(), bars.end());
    return 0;
}

关键说明

  • std::iterator_traits<Iter>::value_type用于获取迭代器Iter指向的元素类型;
  • std::same_as保证元素类型与bar严格匹配,如果需要支持可隐式转换为bar的类型,可以替换为std::convertible_to<typename std::iterator_traits<Iter>::value_type, bar>,但根据需求,严格匹配更合适;
  • 当传入不符合约束的迭代器时,编译器会直接抛出错误,阻止模板实例化,实现类型安全。

内容的提问来源于stack exchange,提问作者user3001150

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 09:10:12