使用模板化comp函数实现unique_copy - 类型推断

时间:2016-01-25 09:56:32

标签: c++ function templates c++11 type-inference

我已经实现了unique_copy的版本,但它确实有效。问题是我必须这样称呼它:

my_unique_copy(
    in.begin(),                 // ok
    in.end(),                   // ok
    out.begin(),                // ok
    equals<Container::iterator> // <--sucks
);

我不喜欢的是等于函数equals<Container::iterator>必须用Container::iterator显式实例化。我认为可以从in.begin()推断类型,类型为Container::iterator。我试图在函数原型中将equals声明为bool()(Iterator,Iterator),但它失败了。

../untitled2/main.cpp:20:32: error: 'parameter' declared as function returning a function
        bool()(Iterator,Iterator) equals){
                                ^
../untitled2/main.cpp:20:34: error: expected ')' before 'equals'
        bool()(Iterator,Iterator) equals){
                                  ^
../untitled2/main.cpp:20:34: error: expected initializer before 'equals'
../untitled2/main.cpp: In function 'int main()':
../untitled2/main.cpp:41:79: error: 'my_unique_copy' was not declared in this scope
     my_unique_copy(in.begin(),in.end(),out.begin(),equals<Container::iterator>);
                                                                               ^

这是代码:

template <typename Iterator>
bool equals(Iterator fst, Iterator snd){
    return *fst==*snd;
}

bool myfunction (int i, int j) {
  return (i==j);
}

template <typename Iterator, typename Comparator>
void my_unique_copy(Iterator begin,
       Iterator end,
       Iterator out_begin,
       Comparator equals){
    if (begin==end){
        return;
    }

    *out_begin=*begin;
    ++begin;

    while (begin!=end){
        if (!equals(out_begin, begin)){
            *(++out_begin)=*begin;
        }
        ++begin;
    }
}

int main(){
    using Container = vector<int>;
    Container in{1,2,2,3};
    Container out(4);

    my_unique_copy(in.begin(),in.end(),out.begin(),equals<Container::iterator>);
    for_each(out.begin(), out.end(), [](int v){cout<<v<<" ";});

    cout<<endl;

    unique_copy(in.begin(),in.end(),out.begin(),myfunction);
    for_each(out.begin(), out.end(), [](int v){cout<<v<<" ";});
}

这就是我想要的:

my_unique_copy(in.begin(), in.end(), out.begin(), equals);

1 个答案:

答案 0 :(得分:2)

如果您将equals实现为函子而不是函数模板,那么基本上可以得到您想要的内容:

struct equals {
    template<typename Iterator>
    bool operator ()(Iterator fst, Iterator snd) const {
        return *fst == *snd;
    }
};

// ...

my_unique_copy(in.begin(), in.end(), out.begin(), equals{});

请注意,因为标准库already has an equal_to functor,您应该选择一个更好地表示您的仿函数与std::equal_to之间差异的其他名称,例如iter_equals。或者,更好的是,您应该使用 std::equal_to而不是通过在调用equals时取消引用迭代器来重新发明轮子,而不是传递迭代器本身(这就是标准库算法确实如此。