ekosman
ekosman

Reputation: 338

containers and operators in c++

I'm requested to implement a simple algorithm which returns a set. It recevies a container (of stl) and an object which implements the binary () opertor. This operator receives two containers and returns a boolean. The returned set will contain every element of the original container which follows some rules. So my algo looks like this:

template<typename Container, typename T, typename Object>
  std::set<T> algo(Container<T>& con, Object obj) {
      std::set<T> out;
      std::vector<T> one;
      std::vector<T> two;
      bool flag_passed_x = false;

    for (typename Container::iterator i = con.begin(); i != con.end(); ++i) {
        one.clear();
        two.clear();
        for (typename Container::iterator j = con.begin(); j != con.end();
            ++j) {
        // split the container
        if (i == j)
            flag_passed_x = true;

        if (!flag_passed_x)
            one.insert(*j);
        else
            two.insert(*j);
        }
        if (obj(one, two)) {
            out.insert(*i);
        }
    }

return out;
}

I also tried the implement a test, by creating the class Kuku whic implements the operator () and send a vector to that algorithm which contains the numbers 0-9.

template<typename Container>
class Kuku {
bool operator()(const Container& low, const Container& high) {
    for(typename Container::iterator i = low.begin(); i != low.end(); ++i) {
        for(typename Container::iterator j = high.begin(); j != high.end(); ++j) {
            if ((int) *j > (int) *i)
            return false;
        }
    }

    return true;
    }
};

Tried to call it with:

int main(){
    std::vector<int> v;
    Kuku<std::vector<int>> kik;

    for (int i = 0; i < 10; i++)
        v.push_back(i);

    line 58 ---> std::set<int> a = algo(v, kik);
    return 0;
}

but I'm getting errors that I can't get rid of:

Description Resource    Path    Location    Type
no matching function for call to 'algo(std::vector<int>&,      Kuku<std::vector<int> >&)'   a.cpp   /dry4   line 58 C/C++ Problem

Description Resource    Path    Location    Type
Invalid arguments '
Candidates are:
std::set<#1,std::less<#1>,std::allocator<#1>> algo(#0 &, #2)
'   a.cpp   /dry4   line 58 Semantic Error

Upvotes: 2

Views: 1221

Answers (2)

AndyG
AndyG

Reputation: 41092

Your code is riddled with errors

You neglected to mention the first error you actually get:

error: 'Container' is not a template
std::set<T> algo(Container<T>& con, Object obj)

You can fix this by modifying your template arguments:

template<template<class...> class Container, typename T, typename Object>
std::set<T> algo(Container<T>& con, Object obj) {

Next, you try to insert into vectors with a value. Use push_back instead:

if (!flag_passed_x)
      one.push_back(*j);
else
      two.push_back(*j);

Next, you have an incomplete iterator declaration for your Container. You need to qualify it as Container<T>::iterator

for (typename Container<T>::iterator i = con.begin(); i != con.end(); ++i) {
// ...
    for (typename Container<T>::iterator j = con.begin(); j != con.end();

Next, you don't expose Kuku's operator() as public:

template<typename Container>
class Kuku {
public:
   bool operator()

Next, you inadvertently try to get a normal iterator from a const container instead of a const_iterator:

for(typename Container::const_iterator i = low.begin(); i != low.end(); ++i) {
        for(typename Container::const_iterator j = high.begin(); j != high.end(); ++j) {

Demo

Upvotes: 2

I think your problem is:

template<typename Container, typename T, typename Object>
   std::set<T> algo(Container<T>& con, Object obj) {

It should be:

template<typename Container, typename T, typename Object>
   std::set<T> algo(Container& con, Object obj) {

Don't try and make Container be a class-template (and that is not how you declare class templates as arguments anyway). Just let it be a simple class (which may well be generated from a template). The particular problem is that std::vector doesn't have a single template argument - it has at least two (T and allocator), and (at least in older versions of C++) there may be implementation specific additional parameters. (I don't know whether they removed that in later versions of the standard.)

If you really want to make Container be a class template, then it needs to be:

template<
   template<typename T1, class Allocator = std::allocator<T1>> typename Container, 
   typename T, 
   typename Object>
std::set<T> algo(Container<T>& con, Object obj) {

Incidentally, I think your loop could be simplified to:

for (auto i = con.begin(); i != con.end(); ++i) {
    const std::vector<T> one(con.begin(), i);
    const std::vector<T> two(i, con.end());
    if (obj(one, two)) {
        out.insert(*i);
    }
}

Upvotes: 1

Related Questions