Concepts-Lite迭代器比较比较值

时间:2017-05-12 19:42:53

标签: c++ c++11 c++-concepts

我已经在这个问题上绞尽脑汁待了几个月。我已经定义了一组松散地描述容器和谓词的概念。

通常,我使用旧式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

进行编译

1 个答案:

答案 0 :(得分:1)

EqualityComparable<T>需要a == ba需要bTa == b类型EqualityComparable。 C ++标准规定容器的Container<vector<MyClass>>要求其值类型为lastN4659 [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远离并自行删除从重载决议。