How to make apply-visitor not discard const qualifier? - c++

Is it possible to write const function with apply_visitor inside?
For example, this code compiles without errors:
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <boost/variant.hpp>
using namespace std;
typedef boost::variant<int,string> vTypeVariants;
struct vType_toN : boost::static_visitor<int>
{
int operator()(int& i) const {
return i;
}
int operator()(const string& str) const{
return str.length();
}
};
class vType{
public:
vType(const int& src) : data(src){}
vType(const std::string& src) : data(src){}
int getLength(){
return boost::apply_visitor(vType_toN(),data);
}
private:
vTypeVariants data;
};
int main(int argc, char ** argv)
{
vType x = string("2");
printf("L=%d",x.getLength());
return(0);
}
Unless you will add const to getLength():
int getLength() const{
return boost::apply_visitor(vType_toN(),data);
}
In such case an error with vast description (2 pages) appears complaining about problem with initializing first argument.
So, the question is: How to use apply_visitor inside const function?

Found out myself.
Forgot const before int in static_visitor class operator definition.
Maybe someone will find this useful as it was not easy to find this out (my original class is much bigger).

Related

Forever hanging destructor

Commenting out some lines of never executed function definition fixes it though. How come?
Full minimal example I've ended up with while deleting unrelated code below.
int main() {
auto tList = tokenize();
tList.front()->~Token(); //hangs forever if the code 10 lines above is not commented, normally I'll have pop_front() here
cout << "never gets printed";
return 0;
}
Normally I'll have
tList.pop_front()
instead of
tList.front()->~Token();
it's here just to demonstrate it more explicitly
Promised code: (also on https://gist.github.com/anonymous/3b8fa11e90c617b35623ba5432050c3e#file-main-cpp-L68)
tokenizer.h
#include <list>
#include <memory>
using namespace std;
#ifndef SGREP_TOKENIZER_H
#define SGREP_TOKENIZER_H
class Token {
public:
virtual ~Token() = default;
virtual bool isChar() const {
return false;
}
};
using TTokenList = list<unique_ptr<Token>>;
TTokenList tokenize ();
#endif //SGREP_TOKENIZER_H
tokenizer.cpp
#include <iostream>
#include <cctype>
#include <string>
#include "tokenizer.h"
using namespace std;
class Char : public Token {
char value;
public:
Char (char value) : value(value){};
bool isChar() const override {
return true;
}
};
TTokenList tokenize () {
TTokenList tList;
tList.push_back(make_unique<Char>('h'));
return tList;
}
main.cpp
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <exception>
#include "tokenizer.h"
using namespace std;
class SyntaxError : public exception {};
class Regex {
public:
virtual size_t match_part(const string& str, size_t begin, size_t maxLen, vector<size_t>& groups) = 0; // groups is a vector of begin,end indices of matched groups (ParenRegexes) (to be able to recreate substrings)
virtual ~Regex() = default;
};
class Char : public Regex {
protected:
vector<char> characterRanges; // pairs -> lower and upper inclusive bound of matching a character (even lower, odd upper), size is always divisible by 2
public:
Char(TTokenList& t, size_t& groupCount) {}
size_t match_part(const string& str, size_t begin, size_t maxLen, vector<size_t>& groups) override {
return 1;
}
};
class SeqRegex: public Regex {
unique_ptr<Regex> a;
public:
SeqRegex(TTokenList& t, size_t& groupCount);
size_t match_part(const string& str, size_t begin, size_t maxLen, vector<size_t>& groups) override { // maxLen by nemelo byt 0:
return 1;
}
};
class OrRegex: public Regex {
SeqRegex a;
public:
OrRegex(TTokenList& t, size_t& groupCount) : a(t, groupCount) {}
size_t match_part(const string& str, size_t begin, size_t maxLen, vector<size_t>& groups) override {
return 1;
}
};
SeqRegex::SeqRegex(TTokenList& t, size_t& groupCount) {
if (t.front()->isChar()) { // Commenting out this portion of code fixes the forever hanging ..
a = make_unique<Char>(t, groupCount);
} else {
cerr << "syntax error, expected [^)]-*^|]" << endl;
throw SyntaxError();
} // ...commenting out up to this point
}
int main() {
auto tList = tokenize();
tList.front()->~Token(); //hangs forever if the code 10 lines above is not commented, normally I'll have pop_front() here
cout << "never gets printed";
return 0;
}
There are, in totality, maybe a dozen unique scenarios where it is appropriate to directly call an object's destructor using the ~T() syntax.
This is no such scenario.
If your intent is to delete the first token in the list, simply calling tList.pop_front() is sufficient.
Calling the destructor directly like you are is going to invoke undefined behavior when the std::unique_ptr object maintaining it later tries to delete it again. So you can't make guarantees about what will or won't happen when this code gets compiled/executed.
You have two classes called Char. They do not have the same definition. This is a violation of the one-definition-rule (ODR) and thus undefined behavior.
I'm just curious why you didn't immediately discover this when you merged the files together.

create an unary_function functor for non-static member function

The code should explain my difficulty. Though the code itself is quite meaningless, I'm planning to add containers in MyClass, and use algorithms with member functions.
#include <cstdlib>
#include <algorithm>
#include <functional>
using namespace std;
class MyClass
{
public:
MyClass() { a = 0; }
~MyClass() {}
private:
int a;
bool tiny_test (int);
int Func();
};
bool MyClass::tiny_test (int b)
{
return a == b;
}
int MyClass::Func()
{
// does not compile
(mem_fun(&MyClass::tiny_test))(this);
// commented below is another attempt, also no success
//mem_fun1_t<bool, MyClass, int> tmp_functor = mem_fun(&MyClass::tiny_test);
//tmp_functor(this);
return 0;
}
int main(int argc, char** argv)
{
return 0;
}
Thanks a lot! Btw, I'm not using a static member function, simply because I believe it must work for non-static member functions.
P.S. Eric, Jarod42, thanks for prompt replies!
bool MyClass::tiny_test (int b)
{ // ^^^^^ You missed this argument
return a == b;
}
Try this:
// Supply one more argument. E.g., 3
(mem_fun(&MyClass::tiny_test))(this, 3);

Unordered_map using pointer address as key

I'm trying to create a map with a custom key, which is an object's pointer address, as mentioned.
I need the address because for now it's the only relevant way to compare between two objects.
from what i understood, the proper way of doing this is by using const char* as key
here is the typedef :
typedef __gnu_cxx::unordered_map<const char*, std::string> TargetsTags;
I'm a bit confused about the following:
how do I create the operator() ?
This is what i used for std::string:
namespace __gnu_cxx {
template<>
struct hash<std::string>
{
hash<const char*> h;
size_t operator()(const std::string &s) const
{
return h(s.c_str());
};
};
}
What about const char*?
And is this the correct way of doing this?
The working example using c++11:
#include <iostream>
#include <unordered_map>
#include <string>
#include <functional>
using namespace std;
class myhash {
public:
size_t operator() (const char *val) const {
return std::hash<std::string>()(val);
}
};
class myequal {
public:
bool operator()(const char *val1, const char *val2) const{
return std::string(val1) == std::string(val2);
}
};
int main() {
std::unordered_map<const char*, string, myhash, myequal> mymap;
mymap["abc"] = "abcd";
mymap["cba"] = "dcba";
std::cout << mymap["abc"] << std::endl;
return 0;
}

correct syntax for merge

This question might appear to be very stupid but I don't understand how to merge two sorted vectors with std::merge.
I tried some code using cplusplus reference.
struct t
{
t(int x):a(x){}
int a;
};
bool operator<(const t& p,const t&b)
{
return p.a<b.a;
}
int main()
{
vector<t> a,b,c;
a.push_back(t(10));
a.push_back(t(20));
a.push_back(t(30));
b.push_back(t(1));
b.push_back(t(50));
merge(a.begin(),a.end(),b.begin(),b.end(),c.begin());
return 0;
}
There is a segmentation fault with this code.
You will want to make sure c is big enough, or grows:
std::merge(a.begin(),a.end(),b.begin(),b.end(),std::back_inserter(c));
Alternatively:
c.resize(a.size() + b.size());
std::merge(a.begin(),a.end(),b.begin(),b.end(),c.begin());
See it Live On Coliru
#include <algorithm>
#include <vector>
#include <iterator>
struct t
{
t(int x):a(x){}
int a;
};
bool operator<(const t& p,const t&b)
{
return p.a<b.a;
}
int main()
{
std::vector<t> a,b,c;
a.push_back(t(10));
a.push_back(t(20));
a.push_back(t(30));
b.push_back(t(1));
b.push_back(t(50));
std::merge(a.begin(),a.end(),b.begin(),b.end(),std::back_inserter(c));
return 0;
}

mem_fun_ref: unresolved overloaded function type

The following code won't compile because of "error: no matching function for call to ‘mem_fun_ref()’" (gcc version 4.4.6).
#include <vector>
#include <string>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
class toto
{
char v[10];
public:
toto(char* t) { memcpy(v, t, 9); }
bool test(const char* var) const { return !strncmp(var, v, 9); }
bool test(const string& var) const { return test(var.c_str()); }
};
int main()
{
vector<toto> t;
t.push_back("1");
t.push_back("2");
string name("2");
vector<toto>::iterator it = remove_if(t.begin(), t.end(),
bind2nd(mem_fun_ref(&toto::test), name)); // <= error
t.erase(it, t.end());
return 0;
}
I found a workaround: creating a
bool testZ(const string& var) const { return testZ(var); }
But I can't seem to find the correct template parameters, if that's even possible, to give to mem_fun_ref (or bind2nd?) to make it compile without my workaround.
Is there anyway to achieve this without my workaround, or is the workaround the "preferred" method?
You should be able to cast it according to C++ overloaded method pointer:
bind2nd(mem_fun_ref((bool (toto::*)(const string&) const) &toto::test), name));