How to fix this C3848 error on vs2013? - c++

I'm trying to implement Best First Search using C++ on VS2013. Below is the code.
//node for tree
struct Node
{
Node(std::string const& s, std::string const& p)
: state(s), path(p)
{}
const std::string state;
const std::string path;
};
//heuristic functor
struct ManhattanDistance
{
std::size_t operator()(std::string const& state, std::string const& goal)
{
std::size_t ret = 0;
for (int index = 0; index != goal.size(); ++index)
{
if ('0' == state[index])
continue;
auto digit = state[index] - '0';
ret += abs(index / 3 - digit / 3) + abs(index % 3 - digit % 3);// distance(row) plus distance(col)
}
return ret;
}
};
//functor to compare nodes using the heuristic function.
template<typename HeuristicFunc>
struct GreaterThan
{
explicit GreaterThan(HeuristicFunc h, std::string const& g = "012345678")
: goal(g), heuristic(h)
{}
bool operator()(Node const& lhs, Node const& rhs) const
{
return heuristic(lhs.state, goal) > heuristic(rhs.state, goal);
return true;
}
const std::string goal;
const HeuristicFunc heuristic;
};
When testing this code in Unit Test, compiler complained that :
Error 1 error C3848: expression having type 'const ai::search::ManhattanDistance' would lose some const-volatile qualifiers in order to call 'size_t ManhattanDistance::operator ()(const std::string &,const std::string &)'
How to understand this error? How to fix it?

Your method std::size_t ManhattanDistance::operator()(std::string const& state, std::string const& goal) is not declared const, yet you try to call it on a const ManhattanDistance object. The compiler is correctly rejecting this ill-formed program.
Change the defining line to declare the method const:
std::size_t operator()(std::string const& state, std::string const& goal) const
// ^^^^^

Related

Iterator gives different results based on usage c++

I recently started c++ programming. I shifted from Java.
I was building my own Iterable class template like this:
template<class T> class Iterable
{
T start,stop;
public:
explicit Iterable(T s,T e) {start=s; stop=e;;}
public:
virtual void next(T& i) =0;
public:
class iterator: public std::iterator<
std::input_iterator_tag, // iterator_category
T, // value_type
long, // difference_type
const T*, // pointer
T // reference
>{
T current;
Iterable<T>* obj;
public:
explicit iterator(T t,Iterable<T>* o) : obj(o) {current=t;}
iterator& operator++() {obj->next(current); return *this;}
iterator operator++(int) {iterator retval = *this; ++(*this); return retval;}
bool operator==(iterator other) const {return current == other.current;}
bool operator!=(iterator other) const {return !(*this == other);}
const T& operator*() const {return current;}
};
iterator begin() {return iterator(start,this);}
iterator end() {return iterator(stop,this);}
};
When i tried to use this iterator, I got different results when invoked differently:
for(auto S=SI.begin();S!=SI.end();S++)
{
cout << *S << "\n";
//cout << contains(seqs,S) << "\n";
if(!contains(seqs,*S))
seqs.push_back(*(new Sequence(*S)));
}
gave different results from:
for(Sequence S : SI)
{
cout << S << "\n";
//cout << contains(seqs,S) << "\n";
if(!contains(seqs,S))
seqs.push_back(*(new Sequence(S)));
}
even in the loop.
My SeqIter class (SI is object of this class) is as follows:
class SeqIter : public flex::Iterable<Sequence>
{
int n;
public:
SeqIter(int s) : Iterable(Sequence(copyList(0,s),s),Sequence(copyList(3,s),s)) {n=s;}
void next(Sequence& s)
{
char ch;
for(int i=0;i<n;i++)
{
ch=nextBase(s[i]);
s[i]=ch;
if(ch!=0)
break;
}
}
};
Sorry if this is too much code, but I do not know how much code is required.
Also, a brief explanation on the Sequence class:
It is a class that has an array of numbers (in this case I tried with 3), and it generates next sequences based on the first, i.e. 000, 100, 200, 300; 010,110 ...
Each digit ranges from 0-3 (both included)
I am unable to understand why both loops give different sequences (first gives 000 100 200 300 010 110 whereas second gives 000 100 200 300 000 110)
I thought both the loops were fundamentally same, and that the first was just the expansion of the second. Is that not so?
Also sequence class: (Sorry for delay, but I guess this is the problem)
class Sequence
{
int size=1;
char* bps;
public:
Sequence() {size=0;}
Sequence(int s)
{
size=s;
bps=new char[s];
}
Sequence(char* arr,int s)
{
size=s;
bps=arr;
}
Sequence(const Sequence& seq)
{
size=seq.size;
bps=new char[size];
strcpy(bps,seq.bps);
}
String toString() const {return *(new String(bps,size));}
inline char* toCharArray() {return bps;}
inline int getSize() const {return size;}
//operator overloading
public:
bool operator==(const Sequence& s2) const
{
if(s2.size!=size)
return false;
String r1=toString();
String r2=s2.toString();
return (r1==r2 || r1==r2.reverse());
}
inline bool operator!=(const Sequence& s2) const {return !operator==(s2);}
const char& operator[](int n) const
{
if(n>=size)
throw commons::IndexOutOfBoundsException(n,size);
return bps[n];
}
char& operator[](int n)
{
if(n>=size)
throw commons::IndexOutOfBoundsException(n,size);
return bps[n];
}
Sequence& operator=(const Sequence& seq)
{
size=seq.size;
bps=new char[size];
strcpy(bps,seq.bps);
}
};
Sorry everyone. Answering my own question after debugging:
In my Sequence class, I was using strcpy in copying char*, where the array did not end with a '\0'
Probably that caused the error:
I read online a bit more to find that the expansion was as follows:
for(Sequence S : seqs)
{
...
}
is equivalent to
for(auto i=SI.begin();i!=SI.end();i++)
{
Sequence S=*i;
...
}
So in the assignment, (S=*i) the data was not properly copied.
Sorry for all the trouble
fixed by removing assignment operator overload, and changing copy-constructor to:
Sequence(const Sequence& seq)
{
size=seq.size;
bps=new char[size];
for(int i=0;i<size;i++)
bps[i]=seq[i];
}

C++ iterator - strange conversion

I've encountered really strange error while working with iterators, and I am not really sure what to think about it:error: could not convert ‘0’ from ‘int’ to ‘CCarList’
CCarList CRegister::ListCars(const string& name, const string& surname) const {
auto ownerIt = findOwner(name, surname);
if (ownerIt == m_owners.end()) return 0; //Error is on this line
//...
}
findOwner:
vector<TOwner*>::const_iterator CRegister::findOwner(const string& name,
const string& surname) const
{
return lower_bound(m_owners.begin(), m_owners.end(), TOwner(name, surname),
[](const TOwner* a, const TOwner& b){return (*a) < b;});
}
m_owners is vector<TOwner*> (TOwner is struct.)
CCarList:
class CCarList {
vector<TCar*>::iterator m_it;
const vector<TCar*>::iterator m_end;
public:
CCarList(vector<TCar*>::iterator it, const vector<TCar*>::iterator end):
m_it(it), m_end(end){}
CCarList(){}
string RZ() const;
bool AtEnd() const;
void Next();
};
ListCars returns a CCarList. You try to return 0, an int. There is no conversion from int to CCarList, so the attempt fails.

Intellisense thinks my symbols are ambiguous

I'm writing my own typesafe enum header-only library at https://bitbucket.org/chopsii/typesafe-enums
The idea is to replace the non-type-safe c-style enum like:
enum ItemCategory
{
BLOCK,
WEAPON
};
with something that's properly type safe.
So far, my solution uses a macro that, for an example equivalent to the above enum, looks like this:
TypesafeEnum(ItemCategory,
(BLOCK)
(WEAPON)
);
And expands to something that looks like this:
template<typename InnerType>
class Wrapped {
public:
InnerType getValue() const { return _val; }
bool operator<(const Wrapped<InnerType>& rhs) const { ; return _val < rhs._val; }
bool operator>(const Wrapped<InnerType>& rhs) const { ; return _val > rhs._val; }
bool operator==(const Wrapped<InnerType>& rhs) const { ; return _val == rhs._val; }
private:
InnerType _val;
protected:
explicit Wrapped<InnerType>(const InnerType& val) : _val(val) {}
void setValue(const InnerType& val) { _val = val; }
};
class WrappedTypeItemCategory : private Wrapped<int>
{
private:
typedef const std::string* strptr;
typedef const std::string* const cstrptr;
explicit WrappedTypeItemCategory(const std::string& label, int val): Wrapped<int>(val), str(&label)
{}
cstrptr str;
public:
static WrappedTypeItemCategory make(const std::string& label, int val)
{
return WrappedTypeItemCategory(label, val);
}
void operator=(const WrappedTypeItemCategory& rhs)
{
;
setValue(rhs.getValue());
const_cast<strptr>(str) = rhs.str;
}
int getValue() const
{
return Wrapped<int>::getValue();
}
const std::string& getString() const
{
return *str;
}
bool operator<(const WrappedTypeItemCategory & rhs) const
{
;
return getValue() < rhs.getValue();
}
bool operator>(const WrappedTypeItemCategory & rhs) const
{
;
return getValue() > rhs.getValue();
}
bool operator==(const WrappedTypeItemCategory & rhs) const
{
;
return getValue() == rhs.getValue();
}
friend std::ostream & operator<<(std::ostream &os, const WrappedTypeItemCategory& rhs)
{
;
return os << *rhs.str << "(" << rhs.getValue() << ")";
}
};
;
namespace {
template<typename T> class ItemCategoryInner : public TypesafeEnumBase
{
public:
static const WrappedTypeItemCategory BLOCK;
static const WrappedTypeItemCategory WEAPON;
static const std::string BLOCKStr;
static const std::string WEAPONStr;
};
template<typename T> const WrappedTypeItemCategory ItemCategoryInner<T>::BLOCK = WrappedTypeItemCategory::make(ItemCategoryInner<T>::BLOCKStr, 0);
template<typename T> const WrappedTypeItemCategory ItemCategoryInner<T>::WEAPON = WrappedTypeItemCategory::make(ItemCategoryInner<T>::WEAPONStr, 1);
template<typename T> const std::string ItemCategoryInner<T>::BLOCKStr("ItemCategory::BLOCK");
template<typename T> const std::string ItemCategoryInner<T>::WEAPONStr("ItemCategory::WEAPON");
struct ItemCategoryTemplateConstantTrick
{};
};
class ItemCategory : public ItemCategoryInner<ItemCategoryTemplateConstantTrick>
{
private:
const WrappedTypeItemCategory* const val;
public:
class InvalidValueError : public std::runtime_error
{
public:
const int val;
InvalidValueError(int val): std::runtime_error(std::string("Invalid value given for ") + "ItemCategory::make"), val(val)
{}
};
ItemCategory(const WrappedTypeItemCategory& value): val(&value)
{}
void operator=(const ItemCategory& rhs)
{
const_cast<const WrappedTypeItemCategory*>(val) = rhs.val;
}
static ItemCategory make(const int& val)
{
if (val == ItemCategory::BLOCK.getValue()) return ItemCategory(ItemCategory::BLOCK);
if (val == ItemCategory::WEAPON.getValue()) return ItemCategory(ItemCategory::WEAPON);
;
throw InvalidValueError(val);
}
const WrappedTypeItemCategory* const getWrappedValue() const
{
return val;
}
int getValue() const
{
return val->getValue();
}
const std::string & getString() const
{
return val->getString();
}
bool operator<(const ItemCategory& rhs) const
{
return *val < *rhs.val;
}
bool operator>(const ItemCategory& rhs) const
{
return *val > *rhs.val;
}
bool operator==(const WrappedTypeItemCategory& rhs) const
{
return *val == rhs;
}
bool operator!=(const WrappedTypeItemCategory& rhs) const
{
return !(*val == rhs);
}
bool operator<=(const WrappedTypeItemCategory& rhs) const
{
return (*val == rhs || *val < rhs);
}
bool operator>=(const WrappedTypeItemCategory& rhs) const
{
return (*val == rhs || *val > rhs);
}
void print(std::ostream& os) const override
{
os << *val;
}
friend std::ostream & operator<<(std::ostream &os, const ItemCategory& rhs)
{
rhs.print(os);
return os;
}
};
;
If I manually pre-expand it, like I have done here - by pre-compiling to file - then intellisense handles it all up until the line that says:
class ItemCategory : public ItemCategoryInner<ItemCategoryTemplateConstantTrick>
At which point it starts thinking ItemCategoryInner and ItemCategoryTemplateConstantTrick are ambiguous, along with many other things on every few lines of the file.
The header that contains this code is included in many places. I know I'm violating the One Definition Rule, which is why I'm using the Template Constant Trick, but I think I need to violate the ODR as my goal is to have an easy to use Macro based typesafe replacement for C++ enums.
I'm not sure if it's the violation of ODR that is the cause of my issues, or something else. I tried __declspec(selectany) but it didn't seem to help - and I would prefer if this macro would be eventually cross-platform, because if it works out, I have other projects I would use it in.
Either way, the .cpp files etc that make use of the enum are able to, and intellisense correctly suggests the options.
However, on a possibly related note, if I don't pre-expand the macro, intellisense isn't able to parse it and it doesn't know what a ItemCategory is at all, even though it compiles and works fine.
I just want my intellisense to work properly with my typesafe enums - it slows down intellisense and confuses it in other code in the same project.

C++ template parameter

I have the following struct:
struct foo
{
bool operator()(char a, char b) const
{
return true;
}
};
pattern<char, foo> p;
And I have the following template class:
template<class T, class S = T>
class pattern
{
public:
int fooBar(std::string lhs, std::string rhs)
{
if(equals(lhs, rhs)) { /* ... */ }
}
private:
bool equals(const std::string &lhs, const std::string &rhs) const
{
S s;
if(s(lhs[0], rhs[0]) //"Term does not evaluate to a
// function taking 2 arguments"
{
return true;
}
}
};
My problem is, that I get the above error. So the question is, how can I reach the functor defined in the foo struct?
In the code you've shown, foo::operator() requires an instance of foo. It's not a static function.
And pattern<T,S> does not hold an instance of T or S.
You can call foo::operator() by instantiating foo somewhere.
bool equals(const std::string &lhs, const std::string &rhs) const
{
return S{}(lhs, rhs);
// ^^ create a temporary instance, for example.
}

C++ - get const access to sub string of a string

Say I have a Storage class:
class Storage
{
public:
const string& get() const { return m_data; }
const char& get(int ind) const { return m_data[ind]; }
const string& get(int s_ind, int e_ind) const { /* TBD */ }
private:
string m_data; ///< Data is so big that part of it is stored on disk
}
Say I have a Writer class that gets const Storage& and needs to access its data.
My question, is there a way to implement:
const string& get(int s_ind, int e_ind) const;
i.e, get const access to only a part of a string.
Notes:
get() is called countless of times and it is the bottleneck of my application. I'd like to avoid allocating new objects when accessing data.
is there a way to implement:
const string& get(int s_ind, int e_ind) const;
i.e, get const access to only a part of a string.
Definitely not.
What is often done - and may resolve your bottleneck - is to create a class that stores a const char* and size_t (or equally begin and end const char*s, or iterators but there's no reason to limit this to use for data in std::strings).
You could then create an object that "references" text inside a string, and use it until any of the events that would invalidate an iterator or reference to those characters happens - see the Standard or e.g. cppreference. It's possible to support stream output, comparisons, indexing etc. driven off the std::string hosted data.
Clearly you won't be able to pass such a class to functions that hardcode std::string type, but you could write it to have a similar interface, which should lessen pain.
Just as a taster (hasn't seen a compiler / flesh out as needed)...
class Text_Ref
{
public:
Text_Ref(const char* p, size_t n) : p_(p), n_(n) { }
// intuitive values for &text_ref[x] BUT text_ref[n] may not be nul
const char& operator[](size_t o) const { return p_[n]; }
*** OR ***
// text_ref[n] is nul BUT can't use &text_ref[x]
char operator[](size_t o) const { return o == n ? '\0' : p_[n]; }
// same design trade off as the operator[] alternatives above
char at(size_t o) const
{
if (o > n) throw std::out_of_range();
return o == n ? '\0' : p_[n];
}
bool empty() const { return n == 0; }
size_t size() const { return n; }
size_t length() const { return n; }
int compare(const char* p) const
{
do
{
if (*p != *p_)
return (int)*p_ - *p;
} while (*p);
return 0;
}
bool operator< (const char* p) const { return compare(p) < 0; }
bool operator<=(const char* p) const { return compare(p) <= 0; }
bool operator==(const char* p) const { return compare(p) == 0; }
bool operator!=(const char* p) const { return compare(p) != 0; }
bool operator>=(const char* p) const { return compare(p) >= 0; }
bool operator> (const char* p) const { return compare(p) > 0; }
private:
const char* p_;
size_t n;
};
inline std::ostream& operator<<(std::ostream& os, const Text_Ref& t)
{
return os.write(t.data(), t.size());
}