Reputation: 85
I am working on a class that I have some problems in finding positions of values in one of elements of the class. I have defined my class as follows:
typedef class Chrom
{
public:
vector<vector < int>> bit;
vector<vector < bool>> jobisconsidered;
vector<vector <float>> WaitingTime;
void variablesresize()
{
int i = 0, j, k;
float a;
std::vector<float> datapoints;
std::ifstream myfile("Input.dat", std::ios_base::in);
i = 0; //making zero counter of characters
myfile.open("Input.dat");//now we reread numerical values
while (!myfile.eof())
{
myfile >> a;
// cout << "i=" << i << '\n';
if (!myfile) // not an int
{
myfile.clear(); // clear error status
myfile.ignore(1); // skip one char at input
}
else
{
datapoints.push_back(a);
++i;
}
}
myfile.close();
Jobs = datapoints[0];
Machines = datapoints[1];
WaitingTime.resize(Machines);
bit.resize(Machines);
for (int i = 0; i < Machines - 1; ++i) WaitingTime[i].resize(Jobs);
bit[i].resize(Jobs);
}
}
} c;
c popcurrent[50];
In the class, bit is a 2D element and if I define it as m*n
, all values in the rows are the same. However, when I want to find position in bit
, for example if popcurrent[0].bit
for 2 rows and 3 columns is = { {3,2,1},{3,2,1} }
, and I want to find position of the first "3
" in the vector is 0 and popcurrent[0].bit[0][0]=3
, I have problems.
Specificaly I tried c++ search a vector for element first seen position with the following commands:
auto p = std::lower_bound(popcurrent[0].bit.begin(), popcurrent[0].bit.end(), 1);
int position = p - popcurrent[0].bit.begin();
But I get following error:
Error 109 error C2893: Failed to specialize function template
'unknown-type std::less<void>::operator ()(_Ty1 &&,_Ty2 &&) const'
I know one way is to use for and if loops. But I wonder is there any more automated way to do this such as build in functions.
Upvotes: 1
Views: 1427
Reputation: 32732
I want to find position of the first "
3
" in the vector is 0 andpopcurrent[0].bit[0][0] = 3
, I have problems. Specificaly I tried c++ search a vector for element first seen position with the following commands:auto p=std::lower_bound(popcurrent[0].bit.begin(), popcurrent[0].bit.end(), 1); int position = p - popcurrent[0].bit.begin();
There are mainly two problems:
Problem - 1: std::lower_bound
takes parameters first
, last
, which are forward-iterator types which defining the partially-ordered range. In your case(popcurrent[0].bit.begin(
)), you are passing a iterator which has the pointed element as a vector of integers (remember std::vector<std::vector<int>>
is an array of vectors(vector<int>
) not integers) for which std::lower_bound
, could not find any definition for operator<
. This is the reason of your error, where compiler complaining that:
" Hey, I don't have a specialisation for operator<
your given range
or vectors, to instantiate the template "
Problem - 2: You can not use std::lower_bound
here, as it needs a strictly sorted array to binary search the value which has been provided. As you provided an unsorted vectors to check, the result won't be correct. See above link to read more:
Solution: You can use std::find_if
which has a time complexity, up to linear in the distance between first
and last
iterator, according to the predicate
provided, which will search for each element until a match is found. This could be an alternative if you do not want to sort each vector in the class, which is actually a 3-dimensional array of vectors.
Following is a sample solution: SEE LIVE HERE
#include <iostream>
#include <vector>
#include <algorithm>
#include <tuple>
typedef std::vector<std::vector < int>> Type ;
struct Chrom // to demonstrate
{
Type bit;
};
std::tuple<int, int, int> findPosition(const std::vector<Chrom>& vec3D, const int& val)
{
int First = 0, Second = 0, Third = -1; // initilize the positions
for(const Chrom& each_chrom: vec3D)
{
for(const std::vector<int>& innerVec: each_chrom.bit)
{
std::vector <int>::const_iterator get_pos;
get_pos = std::find(innerVec.cbegin(), innerVec.cend(), val);
Third = (*get_pos == val) ? get_pos - innerVec.cbegin(): -1; // check val found otherwise -1
if(Third != -1) return std::make_tuple(First, Second, Third); // if found return them
++Second;
}
Second = 0;
Third = -1;
++First;
}
return std::make_tuple(First, Second, Third);
}
int main()
{
// this is a 3 dimensional vector
std::vector<Chrom> popcurrent(2); // position inside the popcurrent
popcurrent[0].bit = { {3,2,1}, // (0,0,0) (0,0,1) (0,0,2)
{3,10,1} }; // (0,1,0) (0,1,1) (0,1,2)
popcurrent[1].bit = { {5,8,11}, // (1,0,0) (1,0,1) (1,0,2)
{4,7,1} }; // (1,1,0) (1,1,1) (1,1,2)
int pos_popcurrent, pos_bit, pos_inner_vec;
for(int val = 1; val <= 12; ++val)
{
std::cout << "\nCurrently looking for: " << val ;
std::tie(pos_popcurrent, pos_bit, pos_inner_vec) = findPosition(popcurrent, val);
(pos_inner_vec != -1) ?
std::cout << " found @ popcurrent[ " << pos_popcurrent << " ].bit[ " << pos_bit << " ][ " << pos_inner_vec <<" ]":
std::cout << " Not found";
}
return 0;
}
Output:
Currently looking for: 1 found @ popcurrent[ 0 ].bit[ 0 ][ 2 ]
Currently looking for: 2 found @ popcurrent[ 0 ].bit[ 0 ][ 1 ]
Currently looking for: 3 found @ popcurrent[ 0 ].bit[ 0 ][ 0 ]
Currently looking for: 4 found @ popcurrent[ 1 ].bit[ 1 ][ 0 ]
Currently looking for: 5 found @ popcurrent[ 1 ].bit[ 0 ][ 0 ]
Currently looking for: 6 Not found
Currently looking for: 7 found @ popcurrent[ 1 ].bit[ 1 ][ 1 ]
Currently looking for: 8 found @ popcurrent[ 1 ].bit[ 0 ][ 1 ]
Currently looking for: 9 Not found
Currently looking for: 10 found @ popcurrent[ 0 ].bit[ 1 ][ 1 ]
Currently looking for: 11 found @ popcurrent[ 1 ].bit[ 0 ][ 2 ]
Currently looking for: 12 Not found
Upvotes: 1
Reputation: 2558
I didn't notice it at first - there's too much irrelevant code - but the problem is quite simple: you're trying to find the first element of type std::vector<int>
not less than value of type int
.
popcurrent[0].bit.begin()
points to the first element of std::vector<std::vector<int>>
, that is a vector. There's no "less than" operator for comparing a vector of ints and an int.
Upvotes: 3