Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;20个概念:元素可替换概念_C++_C++20_C++ Concepts - Fatal编程技术网

C++ C++;20个概念:元素可替换概念

C++ C++;20个概念:元素可替换概念,c++,c++20,c++-concepts,C++,C++20,C++ Concepts,我正在尝试创建一个概念ElementIterable,它可以确定类型是否为嵌套范围。例如,std::vector中的元素是不可编辑的,但是std::vector中的元素(std::vector)是可编辑的。我想到了使用std::iterator_traits的想法,实验代码如下。但是,此ElementIterable概念不能像预期的行为那样工作。有没有办法解决这个ElementIterable概念 template<typename T> concept ElementIterabl

我正在尝试创建一个概念
ElementIterable
,它可以确定类型是否为嵌套范围。例如,
std::vector
中的元素是不可编辑的,但是
std::vector
中的元素(
std::vector
)是可编辑的。我想到了使用
std::iterator_traits
的想法,实验代码如下。但是,此
ElementIterable
概念不能像预期的行为那样工作。有没有办法解决这个
ElementIterable
概念

template<typename T>
concept ElementIterable = requires(typename std::iterator_traits<T>::value_type x)                        //  requires-expression
{
    x.begin();          // must have `x.begin()`
    x.end();            // and `x.end()`
};
函数
Foo
的用法

int number = 1;
    
std::vector<decltype(number)> vector1;
vector1.push_back(number);
Foo(vector1);           //  Element not iterable

std::vector<decltype(vector1)> vector2;
vector2.push_back(vector1);
Foo(vector2);           //  Element not iterable
                        //      but expected behaviour is: Element iterable
int number=1;
std::矢量1;
矢量1.推回(数字);
Foo(向量1);//元素不可分
std::矢量2;
矢量2.推回(矢量1);
Foo(矢量2);//元素不可分
//但预期的行为是:元素不可预测

欢迎提出所有建议。

C++20概念可以根据您的需要而变得愚蠢(例如,文本替换)。在您的情况下,简单模板duck类型应该通过检查您需要存在的内容来完成这项工作,即在您的类型的迭代器函数的结果中检查迭代器函数

考虑到这一点,您可以尝试以下方式:

template<typename T>
concept ElementIterable = requires(T x)
{
    x.begin()->begin();        
    x.end()->end();            
};
模板
概念元素iterable=requires(T x)
{
x、 begin()->begin();
x、 end()->end();
};

问题是
std::iterator\u traits
iterator\u traits
的参数应该是迭代器类型。同时,您希望该概念适用于容器。由于
std::iterator_traits
设计为对SFINAE友好,而且容器不太可能满足足够的旧迭代器概念,因此在检查概念时,很可能
std::iterator_traits
没有成员。这导致概念没有得到满足

为什么不依赖范围标题中的概念?它有一个方便的实用程序来获取满足范围概念的类型的值类型

#include <ranges>

template<typename T>
concept ElementIterable = requires(std::ranges::range_value_t<T> x)
{
    x.begin();          // must have `x.begin()`
    x.end();            // and `x.end()`
};
#包括
模板
概念元素iterable=requires(标准::范围::范围\u值\u t x)
{
x、 begin();//必须有'x.begin()`
x、 end();//和'x.end()`
};
或者,稍微强健一些,不需要重塑标准特征

template<typename T>
concept ElementIterable = std::ranges::range<std::ranges::range_value_t<T>>;
模板
概念元素iterable=std::ranges::range;

如果要询问某个类型是否是一个本身包含范围的范围,只需将
std::range
类型应用两次:

template<typename T>
concept nested_range = std::ranges::range<T> && std::ranges::range<std::ranges::range_value_t<T>>
模板
概念嵌套_range=std::ranges::range&&std::ranges::range

range\u value\u t
从范围的迭代器类型中提取
value\u type

为什么不在类型本身上检查
v.begin()->begin()
v.end()->end()
?是的,修复了它,这是复制提供的代码后留下的。这是一个非常糟糕的概念。它不使用任何现有的标准库概念,因此不能包含它们。它只检查memberwise
begin/end
,而不是允许其他内容的
ranges::begin/end
。总的来说,这不是解决问题的好方法。感谢您解释
std::iterator\u traits
无法生效的原因。
template<typename T>
concept nested_range = std::ranges::range<T> && std::ranges::range<std::ranges::range_value_t<T>>