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.
}
Related
How do i fix this?
I'm getting error: 'this' argument has type const but function is not marked const c++ overload operator
template <class T>
class Rational {
private:
T n = 0;
T d = 1;
public:
Rational() = default;
T numerator() {
return n;
}
T denominator() {
return d;
}
};
template <class T>
inline bool const operator ==(const Rational <T> & lhs, const Rational <T>& rhs) {
return lhs.numerator() * rhs.denominator() == lhs.denominator() * rhs.numerator();
}
My guess is that numerator() and denominator() member functions are not const member functions. Make them const. After that, the above function should work.
BTW, there is no need for the return type to be bool const. Keep it simple and change it to bool.
If numerator() and denominator() are to be used to directly assign to Rationals internal member variables as well as being used in const contexts, you need two sets of overloads. One mutable and one const:
// mutable interface
T& Rational::numerator();
T& Rational::denominator();
// const interface if T may only be a fundamental integral type
T Rational::numerator() const;
T Rational::denominator() const;
// const interface if sizeof(T) may be > sizeof(T*)
T const& Rational::numerator() const;
T const& Rational::denominator() const;
Note, only one of the const interfaces may be used so you need to select one of them.
Here's an example of how it can be done:
#include <iostream>
#include <type_traits>
template<typename T>
class Rational {
public:
// pass by value for fundamental types, by const& for other types
using by_value_or_by_const_ref =
std::conditional_t<std::is_fundamental_v<T>, T, T const&>;
Rational(by_value_or_by_const_ref n, by_value_or_by_const_ref d) :
m_numerator(n), m_denominator(d) {}
// mutable interface
T& numerator() { return m_numerator; }
T& denominator() { return m_denominator; }
// const interface
by_value_or_by_const_ref numerator() const { return m_numerator; }
by_value_or_by_const_ref denominator() const { return m_denominator; }
private:
T m_numerator;
T m_denominator;
};
template<class T>
inline bool operator==(const Rational<T>& lhs, const Rational<T>& rhs) {
// using const interface
return lhs.numerator() * rhs.denominator() ==
lhs.denominator() * rhs.numerator();
}
int main() {
Rational<int> a(10, 20);
Rational<int> b(10, 10);
// using mutable interface
a.denominator() /= 4;
b.numerator() *= 2;
std::cout << std::boolalpha << (a == b) << "\n";
}
I want to create efficient and easy to use value type.
Base of the Value is a boost::variant (and std::variant in the future), but I'm new in it.
And I have some questions:
In the code below, is it necessary to use recursive variant?
Is it possible to not inherit from the boost::variant? Maybe more efficient way exists?
Do you have any comments or suggestions on the code below (it's not fully completed code, but only a draft)?
class Value;
typedef std::string String;
typedef std::vector<char> BinData;
typedef String URL;
typedef unsigned long long UID;
TSW_STRONG_TYPEDEF(std::time_t, Time)
typedef std::vector<Value> ValueArray;
typedef std::vector<String> StringArray;
//typedef std::pair<String, Value> NameValue;
typedef std::list<Value> ValueList;
typedef std::list<String> StringList;
typedef std::map<String, String> StringStringMap;
typedef std::map<String, Value> NameValueMap;
struct monostate
{
monostate() = default;
};
constexpr bool operator<(monostate, monostate) noexcept { return false; }
constexpr bool operator>(monostate, monostate) noexcept { return false; }
constexpr bool operator<=(monostate, monostate) noexcept { return true; }
constexpr bool operator>=(monostate, monostate) noexcept { return true; }
constexpr bool operator==(monostate, monostate) noexcept { return true; }
constexpr bool operator!=(monostate, monostate) noexcept { return false; }
typedef monostate Null;
class Object
{
public:
Object() = delete;
Object(const Object &other) = default;
Object(Object &&other);
Object(const String &name);
Object(String &&name);
Object(const String &name, const NameValueMap &fields);
Object(String &&name, const NameValueMap &fields);
Object(const String &name, NameValueMap &&fields);
Object(String &&name, NameValueMap &&fields);
Object &operator=(const Object &other) = default;
Object &operator=(Object &&other);
public:
const String &get_name() const;
const NameValueMap &get_fields() const;
public:
bool operator<(const Object &other) const noexcept;
bool operator>(const Object &other) const noexcept;
bool operator<=(const Object &other) const noexcept;
bool operator>=(const Object &other) const noexcept;
bool operator==(const Object &other) const noexcept;
bool operator!=(const Object &other) const noexcept;
private:
String name_;
NameValueMap fields_;
};
enum class ValueType
{
Undefined, Null, Array, BinData, Boolean, DoubleNumber, Int64Number, String, Time, Object
};
// Types ordnung need to be same with ValueType ordnung.
/// Base for the Value class
typedef boost::variant<monostate, Null, ValueArray, BinData, bool, double, int64_t, String, Time, Object> ValueBase;
/**
* #brief The Value class, implements common framework value.
*
* This class is a container, which can store multiple values, including Values containers.
*
* #note
* Class based on a variant class. It may be either boost::variant or std::variant in C++17 and higher.
*/
class Value : public ValueBase
{
public:
using ValueBase::ValueBase;
Value() = default;
Value(const String::value_type *v) : ValueBase(String(v)) {}
public:
bool is_array() const { return static_cast<ValueType>(which()) == ValueType::Array; }
bool is_bool() const { return static_cast<ValueType>(which()) == ValueType::Boolean; }
bool is_bindata() const { return static_cast<ValueType>(which()) == ValueType::BinData; }
bool is_double() const { return static_cast<ValueType>(which()) == ValueType::DoubleNumber; }
bool is_int64() const { return static_cast<ValueType>(which()) == ValueType::Int64Number; }
bool is_null() const { return static_cast<ValueType>(which()) == ValueType::Null; }
bool is_object() const { return static_cast<ValueType>(which()) == ValueType::Object; }
bool is_string() const { return static_cast<ValueType>(which()) == ValueType::String; }
bool is_time() const { return static_cast<ValueType>(which()) == ValueType::Time; }
bool is_undefined() const { return static_cast<ValueType>(which()) == ValueType::Undefined; }
public:
bool as_bool() const { return as<bool>(); }
BinData &as_bindata() { return as<BinData>(); }
double as_double() const { return as<double>(); }
int64_t as_int64() const { return as<int64_t>(); }
Object &as_object() { return as<Object>(); }
String &as_string() { return as<String>(); }
Time &as_time() { return as<Time>(); }
ValueArray &as_array() { return as<ValueArray>(); }
public:
ValueType value_type() const { return static_cast<ValueType>(which()); }
public:
template <typename T>
const T& as() const { return boost::get<T>(*this); }
template <typename T>
T& as() { return boost::get<T>(*this); }
template <typename T>
const T& as(const T& default_value) const { return type() == typeid(T) ? boost::get<T>(*this) : default_value; }
template <typename T>
T& as(const T& default_value) { return type() == typeid(T) ? boost::get<T>(*this) : default_value; }
template <typename T> boost::optional<T> as_optional() { return boost::make_optional(type() == typeid(T), as<T>()); }
public:
bool operator==(const ValueBase &other) const { return ValueBase::operator==(other); }
bool operator<(const ValueBase &other) const { return ValueBase::operator<(other); }
bool operator>(const ValueBase &other) const { return !((*this) < other || (*this) == other); }
bool operator<=(const ValueBase &other) const { return ((*this) < other || (*this) == other); }
bool operator>=(const ValueBase &other) const { return !((*this) < other); }
bool operator!=(const ValueBase &other) const { return !((*this) == other); }
private:
// Force compile error, prevent Variant(bool) to be called
Value(void *) = delete;
};
Looks okay to me.
You can do without recursive variants IFF your standard library implementation allows instantiation of the container classes for incomplete types.
I'd note that since everything is tied to the base-class publicly, there is nothing about the implementation that can change without also changing the (binary) interface. Therefore I'd surely implement all the members inline so that the compiler will optimize them even without LTO.
It is not clear to me what to_X members do (possibly just a<X> but possibly something else depending on can_convert()?). If it's just a wrap around as_<> I'd rename them as_X() etc.
You might also want to add optional<>-like members like
template <typename T> T const& get_value_or(T const& default_value) const;
And possibly
template <typename T> optional<T> get() const;
// with boost optional you can prevent a copy²:
template <typename T> optional<T const&> get() const;
This enables code like:
if (auto& s = value.get<String>()) {
std::cout << "The string value is '" << *s << "'\n";
} else {
std::cout << "Value has no string value\n";
}
¹ this is not - yet - standard specified. You can always use Boost Container instead which promises this, as well as non-allocating construction
² just make sure you do not allow the operation on a rvalue, to remove a predictable class of errors, so e.g.
template <typename T> optional<T const&> get()&& = delete;
I have a C++ code that currently looks like this: there is a class hierarchy to do perform some comparison and a list class that uses it. Which comparison operation to use is determined at runtime based on some schema object. Here is the structure:
class A{
bool doComparison(const string& s1, const string& s2) const=0;
}
class B: public A{
bool doComparison(const string& s1, const string& s2) const {
...
}
}
class C: public A{
bool doComparison(const string& s1, const string& s2) const {
...
}
}
template <class, S>
public FancyList{
shared_ptr<A> z_;
vector<S> v;
FancyList(shared_ptr<A> z) : z_(z);
void DoSmth(){
....
z_->doComparison(arg1, arg2);
}
}
typedef FancyList<string> FancyStringList;
// Determine which comparison to use at runtime
shared_ptr<A> c = nullptr;
switch(type):
case int:
c = make_shared<B>();
break;
case double:
c = make_shared<B>();
break;
FancyStringList l(c);
l.push_back("stuff");
C# used to be my main language so this code seemed ok to me. But I was told that the problem with this approach is that it uses virtual functions so there is a slight overhead in a method call. What is the proper C++-way of reorganizing this code so there is no need to have this class hierarchy and no need to use virtual functions?
Contrary to what you want, the overhead of virtual function is unavoidable because the decision of which actual function is called is made in runtime.
If the decision is always made in runtime, the compiler cannot hard-code the function call into the generated machine code. It has to be a indirect function call: to use a pointer to point to a function, and to dereference the pointer before the function call. Virtual function is just one way to do indirect function call.
Template is a way tell the compiler to generate code during compile-time. All template can do is to not introduce overhead when the decision is made during compile-time. It can't help you remove works that must be done in runtime.
If you are still interested in using template, you may consider having the comparator as a template parameter.
template <class T, class Comparator>
class MyList
{
std::vector<T> vec;
Comparator comp;
public:
void do_thing(const T& a, const T& b)
{
vec.push_back(a);
vec.push_back(b);
bool x = comp(vec[0], vec[1]); // for example
std::cout << x;
}
};
In the comparator class, overload the function call operator.
class Compare1
{
public:
bool operator()(const std::string& lhs, const std::string& rhs) const
{
return lhs < rhs;
}
};
class Compare2
{
public:
bool operator()(const std::string& lhs, const std::string& rhs) const
{
return lhs.size() < rhs.size();
}
};
int main()
{
MyList<std::string, Compare1> myli1;
myli1.do_thing("a", "b");
MyList<std::string, Compare2> myli2;
myli2.do_thing("c", "d");
}
You can even hide indirect function call behind comparator class. But it does not remove the overhead.
class A
{
public:
virtual bool doComparison(const std::string& s1, const std::string& s2) const=0;
virtual ~A() = default;
};
class PolymorphicComparator
{
private:
std::shared_ptr<A> comp;
public:
PolymorphicComp(std::shared_ptr<A> c) : comp(c) {}
bool operator()(const std::string& lhs, const std::string& rhs) const
{
return comp->doComparison(lhs, rhs);
}
};
I have a templated class MatchBase with a function for the operator == as such
template<typename Element>
class MatchBase{
virtual bool operator ==(const MatchBase<Element>& m) const{
if(_v1 == m.getFirst() && _v2 == m.getSecond()){
return true;
}
return false;
}
I know have a daughter class Match that is template specialized. The class Place used for the specialization does not have an operator== to do the comparison. Thus I'm trying to override the operator== to work with the class Place.
On the things I have tried :
class Match : public betterGraph::MatchBase<graphmatch::Place>{
public :
Match(const graphmatch::Place& v, const graphmatch::Place& vv) :
betterGraph::MatchBase<graphmatch::Place>(v, vv)
{};
virtual bool operator ==(const Match& m) const{
if(_v1.mass_center == m.getFirst().mass_center && _v2.mass_center == m.getSecond().mass_center){
return true;
}
return false;
}
};
I also tried
virtual bool operator ==(const betterGraph::MatchBase<graphmatch::Place>& m) const{
if(_v1.mass_center == m.getFirst().mass_center && _v2.mass_center == m.getSecond().mass_center){
return true;
}
return false;
}
But I always hit an error of the type :
error: no match for ‘operator==’ (operand types are ‘const AASS::graphmatch::Place’ and ‘const AASS::graphmatch::Place’)
if(_v1 == m.getFirst() && _v2 == m.getSecond()){
Because it tries to compile the method from the Base class.
Is there any way for me to override this function of the base class in the daughter class ? I've read the question here but here it's the method that is specialized while my class is specialized so I don't see how to do a forward declaration :/.
The function may be virtual but it's still initialized when you inherit your base class.
This is essential as you might write something like this:
MatchBase<Place> test = Match(p1,p2);
MatchBase<Place> is the base class of Match yet they are not the same.
Calling MatchBase<Place>::operator==() will still call the function defined in your template base class.
You have now multiple option:
- make the function in the base class a pure virtual
- implement Place::operator==()
- pass a comperator as argument to your base class as argument
The first two should be clear (if not please ask). For the third this might be a one possible way to do it:
template<typename Element, typename Less = std::less<Element>>
class MatchBase {
protected:
Element _v1;
Element _v2;
public:
MatchBase(const Element& v, const Element& vv) : _v1(v), _v2(vv)
{}
virtual bool operator ==(const MatchBase<Element, Less>& m) const {
Less less;
bool v1Equal = !less(_v1, m.getFirst()) && !less(m.getFirst(), _v1);
bool v2Equal = !less(_v2, m.getSecond()) && !less(m.getSecond(), _v2);
return v1Equal && v2Equal;
}
const Element& getFirst() const { return _v1; }
const Element& getSecond() const { return _v2; }
};
struct Place
{
int mass_center;
};
struct PlaceLess
{
bool operator()(const Place& p1, const Place& p2)
{
return p1.mass_center < p2.mass_center;
};
};
class Match : public MatchBase <Place, PlaceLess>
{
public:
Match(const Place& v, const Place& vv) :
MatchBase<Place, PlaceLess>(v, vv)
{};
};
Another way might be to specialize std::less<T> in this context. So you won't need to pass it as template parameter.
template<typename Element>
class MatchBase {
protected:
Element _v1;
Element _v2;
public:
MatchBase(const Element& v, const Element& vv) : _v1(v), _v2(vv)
{}
virtual bool operator ==(const MatchBase<Element>& m) const {
std::less<Element> less;
bool v1Equal = !less(_v1, m.getFirst()) && !less(m.getFirst(), _v1);
bool v2Equal = !less(_v2, m.getSecond()) && !less(m.getSecond(), _v2);
return v1Equal && v2Equal;
}
const Element& getFirst() const { return _v1; }
const Element& getSecond() const { return _v2; }
};
struct Place
{
int mass_center;
};
template<>
struct std::less<Place>
{
bool operator()(const Place& p1, const Place& p2)
{
return p1.mass_center < p2.mass_center;
};
};
class Match : public MatchBase <Place>
{
public:
Match(const Place& v, const Place& vv) :
MatchBase<Place>(v, vv)
{};
};
Of course you could merge these ways so you might override the Less template parameter if needed.
If you don't plan on using predefined types (thinking of int, std::string, etc...) you could also make sure that the class passed as Element must inherit a class/struct that enforces that operator== is implemented:
template <typename T>
struct IComparable
{
virtual bool operator==(const T& other) const = 0;
};
template<typename Element>
class MatchBase {
static_assert(std::is_base_of<IComparable<Element>, Element>::value, "Element must implement comparable");
protected:
Element _v1;
Element _v2;
public:
MatchBase(const Element& v, const Element& vv) : _v1(v), _v2(vv)
{}
virtual bool operator ==(const MatchBase<Element>& m) const {
return _v1 == m._v1 && _v2 == m._v2;
}
};
struct Place : public IComparable<Place>
{
int mass_center;
bool operator==(const Place& other) const
{
return mass_center == other.mass_center;
};
};
class Match : public MatchBase <Place>
{
public:
Match(const Place& v, const Place& vv) :
MatchBase<Place>(v, vv)
{};
};
I have a class like this:
class AI
{
private:
struct Comparator
{
bool operator()(const Town* lfs, const Town* rhs)
{
return GetHeuristicCost(lfs) > GetHeuristicCost(rhs);
}
};
int GetHeuristicCost(const Town* town);
// constructor and variables
};
GetHeuristicCost returns the heuristic from the town parameter to the exit of the path.
What I am trying to do is overload the bool operator for a priority queue but it gives me the error
a nonstatic member reference must be relative to a specific object
I know why it is giving me this error but what I don't know is how to use a nonstatic function inside the Comparator struct.
GetHeuristicCost must be nonstatic
I tried moving GetHeuristicCost inside the Town class to no avail
I need to overload the operator with a struct because I need to use two different bool overloadings on the () for two different circumstances but with the same parameters (two Towns). In other words I need the struct so I can't do this:
bool operator()(const Town* lfs, const Town* rhs)
{
return GetHeuristicCost(lfs) > GetHeuristicCost(rhs);
}
Basically I plan on having two structs like this:
struct Comparator1
{
bool operator()(const Town* lfs, const Town* rhs)
{
return GetHeuristicCost(lfs) > GetHeuristicCost(rhs);
}
};
struct Comparator2
{
bool operator()(const Town* lfs, const Town* rhs)
{
return GetHeuristicCost(lfs) + GetTotalCost (lfs, rhs) > GetHeuristicCost(rhs) + GetTotalCost (lfs, rhs);
}
};
You need to construct instances of the Comparator nested class with a pointer/reference to their "outer" class instance.
class AI
{
private:
struct Comparator
{
const AI &outer;
Comparator(const AI &o):outer(o){}
bool operator()(const Town* lfs, const Town* rhs)const
{
return outer.GetHeuristicCost(lfs) > outer.GetHeuristicCost(rhs);
}
};
int GetHeuristicCost(const Town* town)const;
};
// how to use in code:
AI::Comparator comp(*this);
priority_queue<Town*, vector<Town*>, AI::Comparator> priorityQueue(comp);