Concepts-Lite iterator comparison 比较值
Concepts-Lite iterator comparison compares values
几个月来,我一直在为这个问题绞尽脑汁。我已经定义了一组松散地描述容器和谓词的概念。
一般来说,我使用老式的 for
循环遍历容器,并将参数迭代器与 end(container)
迭代器的相等性进行比较。我想不通的是为什么在给定 Container<T>
时无法编译,使得 T
没有相等比较器 (T::operator==(T other)
)
这些概念绝不是完整的,只是为了学习目的,毫无疑问还有其他方法可以完成我正在做的事情。
问题代码在"queryalgorithms.h"中定义的这个短函数中:
#pragma once
#include <algorithm>
#include "concepts.h"
template<typename C, typename P, typename V = typename C::value_type, typename I = typename C::iterator>
I last(C & collection, I iterator, P predicate) requires Container<C> && Predicate<P, V> && Incrementable<I> {
I out;
for (iterator; iterator != end(collection); iterator++) {
}
return out;
}
失败的测试代码在这里:
#include <iostream>
#include <vector>
#include <algorithm>
#include <forward_list>
#include "queryalgorithms.h"
using namespace std;
class MyClass {
public:
int value;
MyClass(int v): value(v) {};
};
template <typename T>
void Test() {
auto collection = T();
for (auto i = 0; i < 10; i++)
last(collection, begin(collection), [] (auto x) { return true; });
}
int main(int argc, char * argv[]) {
Test<vector<MyClass>>();
return 0;
}
不确定这是否有帮助,但为了完整起见,concepts.h 文件是 here。很多,我觉得它没有增加太多价值,所以我把它放在 pastebin 上。
如上所述,这个小示例仅针对定义了相等比较器的类型进行编译(例如 Test<vector<int>>()
可以正常工作)。 g++ 的编译器错误如下:
/usr/include/c++/6.3.1/bits/stl_algobase.h:800:22: error: no match
for ‘operator==’ (operand types are ‘const MyClass’ and ‘const MyClass’)
if (!(*__first1 == *__first2))
所以我的问题是,为什么编译器将 iterator != end(collection)
的类型推断为值类型 V
而不是迭代器类型 I
?
编辑:我正在使用g++ -fconcepts --std=c++17 -o test test.cc
进行编译
Container<T>
需要 EqualityComparable<T>
,这需要 a == b
左值 a
和 b
类型 T
。 C++ 标准规定容器的 a == b
要求其值类型为 EqualityComparable
(N4659 [container.requirements.general] Table 83)。
在 last
的 require 子句中检查 Container<vector<MyClass>>
实例化 vector
的 ==
运算符,这很可能是根据 std::equal
实现的,我推测是算法在 stl_algobase.h
.
的第 800 行定义
因为 MyClass
不是 EqualityComparable
,所以 vector<MyClass>
不是模型 Container
。值得注意的是,该标准不需要 vector
(或任何容器的)operator==
受到约束,因此您会在检查约束时遇到硬错误,而不是 last
SFINAE-ing 并删除自身来自重载决议。
几个月来,我一直在为这个问题绞尽脑汁。我已经定义了一组松散地描述容器和谓词的概念。
一般来说,我使用老式的 for
循环遍历容器,并将参数迭代器与 end(container)
迭代器的相等性进行比较。我想不通的是为什么在给定 Container<T>
时无法编译,使得 T
没有相等比较器 (T::operator==(T other)
)
这些概念绝不是完整的,只是为了学习目的,毫无疑问还有其他方法可以完成我正在做的事情。
问题代码在"queryalgorithms.h"中定义的这个短函数中:
#pragma once
#include <algorithm>
#include "concepts.h"
template<typename C, typename P, typename V = typename C::value_type, typename I = typename C::iterator>
I last(C & collection, I iterator, P predicate) requires Container<C> && Predicate<P, V> && Incrementable<I> {
I out;
for (iterator; iterator != end(collection); iterator++) {
}
return out;
}
失败的测试代码在这里:
#include <iostream>
#include <vector>
#include <algorithm>
#include <forward_list>
#include "queryalgorithms.h"
using namespace std;
class MyClass {
public:
int value;
MyClass(int v): value(v) {};
};
template <typename T>
void Test() {
auto collection = T();
for (auto i = 0; i < 10; i++)
last(collection, begin(collection), [] (auto x) { return true; });
}
int main(int argc, char * argv[]) {
Test<vector<MyClass>>();
return 0;
}
不确定这是否有帮助,但为了完整起见,concepts.h 文件是 here。很多,我觉得它没有增加太多价值,所以我把它放在 pastebin 上。
如上所述,这个小示例仅针对定义了相等比较器的类型进行编译(例如 Test<vector<int>>()
可以正常工作)。 g++ 的编译器错误如下:
/usr/include/c++/6.3.1/bits/stl_algobase.h:800:22: error: no match
for ‘operator==’ (operand types are ‘const MyClass’ and ‘const MyClass’)
if (!(*__first1 == *__first2))
所以我的问题是,为什么编译器将 iterator != end(collection)
的类型推断为值类型 V
而不是迭代器类型 I
?
编辑:我正在使用g++ -fconcepts --std=c++17 -o test test.cc
Container<T>
需要 EqualityComparable<T>
,这需要 a == b
左值 a
和 b
类型 T
。 C++ 标准规定容器的 a == b
要求其值类型为 EqualityComparable
(N4659 [container.requirements.general] Table 83)。
在 last
的 require 子句中检查 Container<vector<MyClass>>
实例化 vector
的 ==
运算符,这很可能是根据 std::equal
实现的,我推测是算法在 stl_algobase.h
.
因为 MyClass
不是 EqualityComparable
,所以 vector<MyClass>
不是模型 Container
。值得注意的是,该标准不需要 vector
(或任何容器的)operator==
受到约束,因此您会在检查约束时遇到硬错误,而不是 last
SFINAE-ing 并删除自身来自重载决议。