2017-05-12 97 views
0

我已经在这个几个月里开始关闭了我的大脑。我已经定义了一组概念,它们粗略地描述了容器和谓词。Concepts-Lite迭代器比较比较

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

回答

1

Container<T>需要EqualityComparable<T>需要a == b为左值aTb编译。 C++标准说,容器的a == b要求其值类型为EqualityComparableN4659 [container.requirements.general] Table 83)。 检查Container<vector<MyClass>>last的要求条款中实例化vector==运算符,最有可能按照std::equal实现,我推测这是的800行上定义的算法。

由于MyClass不是EqualityComparable,vector<MyClass>不是型号Container。该标准明显不要求vector(或任何容器的)operator==受到限制,因此您会在检查约束时发生硬错误,而不是从过载解析中删除自身。

+0

不可否认,我搞乱了'容器'的定义与你引用的标准有关,所以非常感谢。我对容器的定义(注意它是一个自定义定义)要求“容器”本身是“EqualityComparable”而不是“Container :: value_type”。调整到'Container'的'EqualityComparable'的正确定义会导致您在答案中指定的错误更短。但是,我不认为这回答了如前所述的原始问题 – Howard

+0

更改此子句:“上一个要求子句实例化向量的赋值运算符...”到“...实例化向量的相等运算符..”,我将接受这个答案。这个问题是由于我把'Container'的'EqualityComparable'的定义搞乱了,而不是它的值类型。谢谢 – Howard

+0

Woops,那里有巨大的思考。 – Casey