我已经在这个问题上绞尽脑汁待了几个月。我已经定义了一组松散地描述容器和谓词的概念。
通常,我使用旧式for
循环遍历容器,并将参数迭代器的相等性与end(container)
迭代器进行比较。我无法弄清楚的是,当Container<T>
T
没有相等比较器(T::operator==(T other)
)
这些概念绝不是完整的,仅仅是为了学习目的,毫无疑问是其他方法可以完成我正在做的事情。
问题代码在&#34; queryalgorithms.h&#34;中定义的这个简短函数中:
#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
答案 0 :(得分:1)
EqualityComparable<T>
需要a == b
,a
需要b
,T
和a == b
类型EqualityComparable
。 C ++标准规定容器的Container<vector<MyClass>>
要求其值类型为last
(N4659 [container.requirements.general] Table 83)。
检查vector
上的require子句中的==
实例化std::equal
的{{1}}运算符,这很可能是根据stl_algobase.h
实现的,我推测它是算法在MyClass
的第800行定义。
由于EqualityComparable
不是vector<MyClass>
,Container
不会对vector
进行建模。该标准显然不需要operator==
(或任何容器)last
进行约束,因此您会在检查约束时遇到严重错误,而不是 var currentChoice = cc.DropdownListEntries.Cast<ContentControlListEntry>()
.FirstOrDefault(cl => cl.Text == cc.Range.Text)
?.Value;
SFINAE远离并自行删除从重载决议。