non static member in static cpp - c++

The below program is giving as error invalid use of mep in static function
When i declaring mep also as static giving as error undefined reference to mep
when i am declaring comp as non static and also mep as non static
i am giving error invalid use of non static member in sort
what should I do I have to submit this solution class in leetcode?
class Solution {
public:
unordered_map<char,int>mep;
static bool comp(string a,string b){
int n = min(a.size(),b.size());
for(int i=0;i<n;i++){
int diff = mep[a[i]]-mep[b[i]];
if(diff<0)return false;
if(diff>0)return true;
}
return true;
}
bool isAlienSorted(vector<string>& words, string order) {
for(int i=0;i<order.size();i++){
mep[order[i]]=i;
}
vector<string>temp;
temp=words;
sort(temp.begin(),temp.end(),comp);
return temp==words;
}
};
I know other approach for comparator can be lambda function , which one is efficient the above or lambda?

Declare a custom comparator type, using that as the groundwork for your eventual comparator argument for std::sort. In the process, you gain re-usability; something sorely lacking with a static implementation.
class Solution {
public:
struct Comp
{
unordered_map<char, int> mep;
bool operator()(std::string const& a, std::string const& b)
{
size_t n = min(a.size(), b.size());
for (size_t i = 0; i<n; i++) {
int diff = mep[a[i]] - mep[b[i]];
if (diff<0)
return false;
if (diff>0)
return true;
}
return true;
}
};
bool isAlienSorted(vector<string> const& words, string order)
{
Comp comp;
for (int i = 0; i<order.size(); i++) {
comp.mep[order[i]] = i;
}
vector<string>temp = words;
sort(temp.begin(), temp.end(), comp);
return temp == words;
}
};
Regarding your last question, compile to optimized code and measure with a sound benchmark (not as easy as it sounds). If there even is a noticeable difference, my money is on the lambda (which is pretty much what we have above anyway) for no other reason than because of the stronger likelihood the compiler will inline the comparator within the std::sort expansion.

You cannot access a non-static member variable inside a static member function. In addition, you should define the static member variables outside of the class as well. The below code works fine, without any compilation warnings and errors.
#include <string>
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
using namespace std;
class Solution {
public:
static unordered_map<char, int> mep;
static bool comp(string a, string b) {
int n = min(a.size(), b.size());
for (int i = 0; i < n; i++) {
int diff = mep[a[i]] - mep[b[i]];
if (diff < 0)return false;
if (diff > 0)return true;
}
return true;
}
bool isAlienSorted(vector<string>& words, string order) {
for (size_t i = 0; i < order.size(); i++) {
mep[order[i]] = i;
}
vector<string> temp;
temp = words;
sort(temp.begin(), temp.end(), comp);
return temp == words;
}
};
unordered_map<char, int> Solution::mep;
void main()
{
}

The below program is giving as error invalid use of mep in static
function
Because static function (comp) in C++ cannot access non-static variable (mep)
When i declaring mep also as static giving as error undefined
reference to mep
A static variable of a class need to have a definition not just declaration. So give mep an inittialize.

You can pass the unordered_map as a parameter to the comp function. That way you won't be accessing the non-static object but it will require you to write your own sorting algorithm:
static bool comp(const unordered_map<char, int>& map_mep, string a, string b)
{
int n = min(a.size(), b.size());
for (int i = 0; i < n; i++) {
// this way there is no non-static involved
int diff = map_mep[a[i]] - map_mep[b[i]];
if (diff < 0)return false;
if (diff > 0)return true;
}
return true;
}
Because mep is not a static member of the class a static function cannot see it. You should set mep to be static in order to fix this.

Related

Is there a size() member function for std::pair?

I was following a hash table implementation tutorial and came across this:
class HashTable {
private:
static const int hashGroups = 10;
std::list<std::pair<int,std::string>> table[hashGroups];
bool HashTable::isEmpty() const {
int sum{};
for(int i{}; i < hashGroups; i++) {
sum += table[i].size();
}
if(!sum) {
return true;
}
return false;
}
In the isEmpty() member function, why is table[i].size() valid? In my interpretation, table is a list of pairs, therefore, table[i] should return a pair at index [i]. However, there are no member function size() in std::pair.
table is an array of std::list of std::pair, so table[i] is a std::list and it has size() function.

How to init a class const static struct using some statement in C++

There is a const static std::map belonging to a class. Is there a kind of formation which can form the following code :
// file A.h
class A {
public:
const static std::map<std::string, int> m_name2code;
public:
static int getCode(std::string name);
private:
const static char *name[3];
}
// file A.cpp
const char * A::name = {
"hello", "the", "world" }
for (int index = 0; index < 3; ++index) {
m_name2code.insert(std::string(name[i]), i+1);
}
As the code above, I was wondering if there is some syntax to use control-statement to init the class-const-static member?
Thank you very much...
You’d separate the initialization into two phases:
Build the map in a function and return the result.
Initialize the static variable from the result of the function.
For example:
namespace {
std::map<std::string, int> build_map() {
std::map<std::string, int> rc;
const char * A::name = { "hello", "the", "world" };
for (int index = 0; index < 3; ++index) {
rc.emplace(std::string(name[index]), index+1);
}
return rc;
}
}
std::map<std::string, int> const A::m_name2code = build_map();
If you want to go extra fancy you can even initialize a map (although not a std::map) at compile time using constexpr (see, e.g., my CppCon 2016 presentation: Constant Fun).

Using sort and function object , but the function object cannot modify member variables

I wrote the code like the below, I don't know why the member variable flag did't equal 1 after sort process? Can someone give me suggestion.
Code:
class Func{
public:
int flag;
Func()
{
flag = 0;
}
bool operator()(int &l, int &r)
{
if(l==r)
{
flag = 1;
}
return l > r;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
vector<int> a;
int b[] = {11,8,7,6,4,3,4,1};
for(int i = 0; i <sizeof(b)/sizeof(b[0]); i++)
{
a.push_back(b[i]);
}
Func FuncObj = Func();
std::sort(begin(a), end(a), FuncObj);
return 0;
}
According to reliable documentation, std::sort accepts the function object by value. This means the Func being used by std::sort is a copy of FuncObj. This means that when 4 is compared with 4, the copy's flag variable is set to 1, and FuncObj is unchanged. The copy is destroyed when std::sort returns, so this flag is lost.
The simplest solution define int flag as static int flag to that all instances of Func share the same Flag.
If this is not an option, different Funcs must have their own flag, my inclination was to go with a std::shared_ptr. Each default constructed Func would have had it's own flag and shared this flag with any copies made.
However Benjamin Lindley reminds of std::reference_wrapper and this provides a much more convenient solution for the problem. The wrapper is passed by value and copied rather then the Func it references, allowing the source Func to be modified inside std::sort.
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
class Func{
public:
int flag;
Func(): flag(0)
{
}
bool operator()(int &l, int &r)
{
if(l==r)
{
flag = 1;
}
return l > r;
}
};
int main()
{
std::vector<int> a = {11,8,7,6,4,3,4,1};
Func FuncObj = Func();
std::sort(begin(a), end(a), std::reference_wrapper<Func>(FuncObj));
std::cout << FuncObj.flag;
return 0;
}

Custom Sort Function

I have a class
class Foo {
private:
unsigned int n;
std::vector<double> label;
public:
//Methods for getting/setting the private variables
std::vector<double>& getLabel(){ //This method is NOT exclusively used for sorting
return label;
}
}
I have another class that contains a vector of Foo and I would like to sort the vector based on the label.
bool OtherClass::sort(const Foo &a, const Foo &b){
for unsigned int i=0; i< a.getLabel().size(); i++){
if (a.getLabel().at(i) != b.getLabel().at(i)){
return a.getLabel().at(i) < b.getLabel().at(i);
}
}
return false;
}
However, this fails to compile. I think it is related to the fact that I am calling getLabel() and the compiler needs me to ensure that the function is constant. If I modify the sorting function to this:
bool OtherClass::sort(const Foo &a, const Foo &b){
Foo A, B;
A=a;
B=b;
for unsigned int i=0; i< A.getLabel().size(); i++){
if (A.getLabel().at(i) != B.getLabel().at(i)){
return A.getLabel().at(i) < B.getLabel().at(i);
}
}
return false;
}
It is clearly a kludgy workaround and I would really like to understand:
Why the first version doesn't compile
Why the second version compiles
How can I modify the first version WITHOUT changing (i.e. adding const) the getLabel() method and have it compile

Static function call not working (C++)

For some reason the following code gives a compiler error in DevC++: [Error] cannot declare member function 'static double* Sort::bubbleSort(double*, int)' to have static linkage [-fpermissive]
BubbleSort.cpp:
#include <iostream>
#include "Sort.h"
int main(int argc, char** argv) {
double list[] = {4.0, 4.5, 3.2, 10.3, 2.1, 1.6, 8.3, 3.4, 2.1, 20.1};
int size = 10;
double* sortedList = Sort::bubbleSort(list, size);
return 0;
}
Sort.h:
class Sort
{
public:
static double* bubbleSort (double list[], int size);
}
;
Sort.cpp:
#include "Sort.h"
#include <algorithm> // std::swap
static double* Sort::bubbleSort (double list[], int size)
{
bool changed = true;
do
{
changed = false;
for (int j = 0; j < size - 1; j++)
{
if (list[j] > list[j +1])
{
std::swap(list[j], list[j + 1]);
changed = true;
}
}
}
while (changed);
return list; // return pointer to list array
}
Essentially, I'm trying to call the bubbleSort function without creating a Sort object. The code works fine if I create an object first.
What could be causing the error?
Thanks for any suggestions.
The static modifier goes in Sort.h, but not in Sort.cpp.
That's because it means two different things in the two contexts.
When used inside a class declaration, static indicates that the method it refers to is a class method (that you should use without a object reference), rather than a instance method (that you need a object reference to invoke).
When used inside the implementation file (i.e. outside of a class declaration), it indicates that the method it refers to should have static linkage, which means it should not be made visible from outside the object file that contains it. From an object oriented point of view, these functions are private to the file that contains them. It's pretty obvious that this cannot work if other files (which are using your class) should access the method.
Remove the static keyword in the .cpp file. Also, you do not need to return the pointer list since only the contents of the array change change, not the array itself. You can keep using the pointer that you put into the function. sortedList will point to the same memory location as list at the end of your main function.
If all that is in your Sort class is this one static member, there is absolutely no need for a class.
double* bubbleSort (double list[], int size)
{
bool changed = true;
do
{
changed = false;
for (int j = 0; j < size - 1; j++)
{
if (list[j] > list[j +1])
{
std::swap(list[j], list[j + 1]);
changed = true;
}
}
}
while (changed);
return list; // return pointer to list array
}
Additionally, there is no need to return the pointer to the list because you are modifying the list as you sort it (double list[] is the same as double* list, and since you are changing the values in your routine, the pointer to the first element will still be the same, but the values in the array will be swapped around).
void bubbleSort (double list[], int size)
{
bool changed = true;
do
{
changed = false;
for (int j = 0; j < size - 1; j++)
{
if (list[j] > list[j +1])
{
std::swap(list[j], list[j + 1]);
changed = true;
}
}
}
while (changed);
}
You should make the function free-standing and if you need a class method, make it call the free-standing function with the correct parameters.