I recently stumbled upon a interesting problem. The problem is, in the clas Filter, i don't have any problem calling getKriterium().ohodnot().
But when I want to call it in for example Filter_FI(), it doesn't work.
class Filter
{
public:
Filter() {};
SortedSequenceTable<H, O> vyfiltruj(SortedSequenceTable<H, O> pVstup) {
for (TableItem<H, O> *prem : pVstup) {
if (splnaKriterium(O)) {
table.insert(O);
}
}
return table;
}
virtual ~Filter() {};
void setKriterium(Kriterium<O, T>* pKriterium) { aKriterium = pKriterium; };
Kriterium<O, T>* getKriterium() { return aKriterium; };
protected:
virtual bool splnaFilter(const O& pObject, Kriterium<O, T>& pKrit) = 0;
private:
Kriterium<O, T>* aKriterium;
SortedSequenceTable<T, O>* table;
};
template<typename O, typename T, typename H>
class Filter_fi : public Filter<O, T, H>
{
public:
Filter_fi() {};
void setAlpha(T pAlpha) { alphaPARAM = pAlpha; };
T getAlpha() { return alphaPARAM; };
void test() {
getKriterium().ohodnot()// Here I want to call the function .ohodnot(), But it will not let me...
}
virtual ~Filter_fi() {};
protected:
virtual bool splnaFilter(const O& pObject) override { return (alphaPARAM); };
private:
T alphaPARAM;
};
I would be very glad if you could help me fix the problem.
Related
I need to write Stream class with a template Write function to accept any type and write it to stream.
I write a Stream class and a StreamWriter to partially specialize Write function, but compiler can't find static function of StreamWriter with base class of AInt class.
template<typename T>
class AType {
public:
T rawValue;
void Add(T v) { rawValue += v; }
void Sub(T v) { rawValue += v; }
void Mul(T v) { rawValue *= v; }
void Mod(T v) { rawValue %= v; }
};
class AInt : public AType<int> {
public:
using AType<int>::Add;
using AType<int>::Sub;
using AType<int>::Mul;
using AType<int>::Mod;
};
class AFloat : public AType<float> {
public:
using AType<float>::Add;
using AType<float>::Sub;
using AType<float>::Mul;
};
class AStream;
template<typename T>
class AStreamWriter {
public:
static bool Write(AStream *stream, T v);
};
class AStream {
public:
template<typename T>
bool Write(T v) {
return AStreamWriter<T>::Write(this, v);
}
};
template<typename T>
class AStreamWriter<AType<T>> {
public:
static bool Write(AStream *stream, AType<T> v) {
//Do somethings
return true;
}
};
int main() {
AInt x{10};
AStream stream;
stream.Write(x); //Error, Compiler can't find AStreamWriter<AInt>::Write
}
Is there any way to fix this problem?
Your specialization AStreamWriter<AType<T>> is unrelated to AStreamWriter<AInt> (and you call AStreamWriter<AInt>::Write(AStream*, AInt), not AStreamWriter<AType<int>>::Write(AStream*, AType<int>)).
overload or simple template function might be a alternative...
template<typename T>
static bool Write(const AType<T>&) { return true; }
I solve the problem with c++ concept.
IsAType is a concept that accepts all subclasses of AType.
template<typename T>
class AType {
public:
using RawType = T;
T rawValue;
void Add(T v) { rawValue += v; }
void Sub(T v) { rawValue += v; }
void Mul(T v) { rawValue *= v; }
void Mod(T v) { rawValue %= v; }
};
template<typename T>
concept IsAType = std::is_base_of_v<AType<typename T::RawType>, T>;
class AInt : public AType<int> {
public:
using AType<int>::Add;
using AType<int>::Sub;
using AType<int>::Mul;
using AType<int>::Mod;
};
class AFloat : public AType<float> {
public:
using AType<float>::Add;
using AType<float>::Sub;
using AType<float>::Mul;
};
class AStream;
template<typename T>
class AStreamWriter {
public:
static bool Write(AStream *stream, T v);
};
class AStream {
public:
template<typename T>
bool Write(T v) {
return AStreamWriter<T>::Write(this, v);
}
};
template<IsAType T>
class AStreamWriter<T> {
public:
static bool Write(AStream *stream, T v) {
//Do somethings
return true;
}
};
int main() {
AInt x{10};
AStream stream;
stream.Write(x);
}
Hi so I recently tried to create sort of a Filters for a Database which must meet specific Criteria. I am sort of a amateur when it comes to C++ Polymorfism. So I really don't know Where is problem anymore.
Kriterium.h Header ->
//Kriterium.h
#pragma once
#include "Uzemna_Jednotka.h"
#include "Politicke_Strany.h"
template <typename O, typename T>
class Kriterium
{
public:
Kriterium() {};
virtual T ohodnot( O& pObject) = 0;
virtual ~Kriterium() {};
};
template <typename T>
class KriteriumUJ : public Kriterium<Uzemna_Jednotka, T> {
public:
KriteriumUJ() {};
virtual T ohodnot( Uzemna_Jednotka& pJednotka) = 0;
virtual ~KriteriumUJ() {};
};
class KriteriumPatriDo : public KriteriumUJ<bool> {
public:
KriteriumPatriDo() : KriteriumUJ() {};
bool ohodnot( Uzemna_Jednotka& pJednotka) override { return pJednotka.checkIFPatriDoVUC(aVyssiCelok); };
void setVyssiCelok(Uzemna_Jednotka* pJednotka) { aVyssiCelok = pJednotka; };
Uzemna_Jednotka* getVyssiCelok() { return aVyssiCelok; };
~KriteriumPatriDo() {};
private:
Uzemna_Jednotka* aVyssiCelok;
};
Filter.h Header ->
//Filter
#pragma once
#include "Kriterium.h"
#include "Uzemna_Jednotka.h"
#include "structures/heap_monitor.h"
#include "structures/table/sorted_sequence_table.h"
#include "structures/table/unsorted_sequence_table.h"
template<typename O, typename T, typename H>
class Filter
{
public:
Filter() {};
virtual UnsortedSequenceTable<H, O> vyfiltruj(UnsortedSequenceTable<H, O> pVstup, Kriterium<O, T>& pKriterium) = 0;
protected:
virtual bool splnaFilter(O& pObject, Kriterium<O,T>& pKriterium) = 0;
private:
};
template<typename O, typename T, typename H>
class Filter_fi : public Filter<O, T, H>
{
public:
Filter_fi() {};
void setAlpha(T pAlpha) { alphaPARAM = pAlpha; };
T getAlpha() { return alphaPARAM; };
UnsortedSequenceTable<H, O> vyfiltruj(UnsortedSequenceTable<H, O> pVstup, Kriterium<O, T>& pKriterium) override
{
UnsortedSequenceTable<H, O>* table = new UnsortedSequenceTable<H, O>;
for (TableItem<H, O>* prem : pVstup) {
if (splnaFilter(prem->accessData(), pKriterium)) {
table->insert(prem->getKey(), prem->accessData());
}
}
return *table;
};
virtual ~Filter_fi() {};
protected:
virtual bool splnaFilter(O& pObject, Kriterium<O, T>& pKriterium) override { return pKriterium.ohodnot(pObject) == alphaPARAM; };
private:
T alphaPARAM;
};
template<typename O, typename T, typename H>
class Filter_FI : public Filter<O, T, H>
{
public:
Filter_FI() {};
void setParametre(T pMin, T pMax) { aMin = pMin, aMax = pMax; };
T getMin() { return aMin; };
T getMax() { return aMax; };
UnsortedSequenceTable<H, O> vyfiltruj(UnsortedSequenceTable<H, O> pVstup, Kriterium<O, T>& pKriterium) override
{
UnsortedSequenceTable<H, O>* table = new UnsortedSequenceTable<H, O>;
for (TableItem<H, O>* prem : pVstup) {
if (splnaFilter(prem->accessData(), pKriterium)) {
table->insert(prem->getKey(), prem->accessData());
}
}
return *table;
};
virtual ~Filter_FI() {};
protected:
virtual bool splnaFilter(O& pObject, Kriterium<O, T>& pKriterium) override {
T hodnota = pKriterium.ohodnot(pObject);
return (aMin <= hodnota && hodnota <= aMax);
};
//Kriterium<O, T>* aKriterium;
private:
T aMin;
T aMax;
};
class Filter_UJ_Prislusnost : public Filter_fi <Uzemna_Jednotka*, bool, int> {
public:
Filter_UJ_Prislusnost(): Filter_fi() {};
virtual ~Filter_UJ_Prislusnost() {};
};
*The problem is if I try to call ->
aFilter_Typ.setAlpha(UzemnaJednotka_TYP_Enum::Obec);
aFilter_Typ.vyfiltruj(aTabulkaUJ, aKriterium);
-> aKriterium gives a
C++ a reference of type (not const-qualified) cannot be initialized with a value of type
[![Description of the Error][1]][1]
Filter and Kriterium are initialized like this ->
Filter_UJ_Name aFilter_Meno;
KriteriumPatriDo aKriterium;
I would be very glad if you could help me fix the problem.*
For example, I have a class template:
template <typename T>
class base {
public:
void set(T data) { data_=data; }
private:
T data_;
};
And for a certain type I would like to add a function, but also have functions from the template class.
template <>
class base<int>{
public:
void set(int data) { data_=data; }
int get(){ return data_;} //function specific to int
private:
int data_;
}
How to do that without copying all members from the template class?
With inheritance:
template <typename T> struct extra {};
template <> struct extra<int> {
public:
int get() const;
};
template <typename T>
class base : public extra<T> {
friend class extra<T>;
public:
void set(T data) { data_=data; }
private:
T data_ = 0;
};
int extra<int>::get() const{ return static_cast<const base<int>*>(this)->data_;}
Demo
You can do this by using enable_if from type_traits to enable the get function only when the template parameter is int. One example is shown below.
#include <type_traits>
template <typename T>
class base {
public:
template <typename X=T,
std::enable_if_t< std::is_same<X,typename T>::value
&& std::is_same<X,int>::value, bool> = false>
int get() { return data_; }
void set(T data) { data_=data; }
private:
T data_;
};
Problem
Motivated by Sean Parent's "Runtime Polymorphism" I implemented a Serializable class that uses type-erasure to dispatch Serializable::serialize(...) ⟶ obj.serialize(...), where obj is a wrapped object.
struct Serializable
{
template <typename T>
Serializable(T obj)
: m_self(std::make_unique<Model<T> >(std::move(obj))) {}
/// Writes itself to a write storage
void serialize(Storage& outStream)
{ return m_self->serialize(outStream); }
private:
struct Concept
{
virtual ~Concept() = default;
virtual void serialize(Storage& outStream) = 0;
};
template <typename T>
class Model final : public Concept
{
public:
Model(T x) : m_data(std::move(x)) {}
private:
void serialize(Storage& outStream) override
{ m_data.serialize(outStream); }
private:
T m_data;
};
private:
std::unique_ptr<Concept> m_self;
};
Now I would like to extend Serializable with another model class that would dispatch Serializable::serialize(...) to a free function with obj as an argument: Serializable::serialize(...) ⟶ serialize(obj, ...)
Then I would like a template constructor of Serializable to decide which model to use by checking the existence of either T::serialize(...) or serialize(const T&, ...)
Question
Is it possible by any means (e.g., SFINAE) to automatically construct Serializable so that it uses a method serialization if possible and free-function serialization otherwise?
Feel free to use any C++ standard up to C++17.
You can devise your own trait to find out whether the class has the correct serialize member. There are several ways to do it, this is one of them:
template <class T, class = void>
struct HasMemberSerialize : std::false_type
{};
template <class T>
struct HasMemberSerialize<T, std::void_t<decltype(std::declval<T>().serialize(std::declval<Storage&>()))>> : std::true_type
{};
[Live example]
Then, add a new template parameter to Model and use the trait to find its argument:
struct Serializable
{
template <typename T>
Serializable(T obj)
: m_self(std::make_unique<Model<T, HasMemberSerialize<T>::value> >(std::move(obj))) {}
/// Writes itself to a write storage
void serialize(Storage& outStream)
{ return m_self->serialize(outStream); }
private:
struct Concept
{
virtual ~Concept() = default;
virtual void serialize(Storage& outStream) = 0;
};
template <typename T, bool Member>
class Model;
private:
std::unique_ptr<Concept> m_self;
};
template <typename T>
class Serializable::Model<T, true> final : public Serializable::Concept
{
public:
Model(T x) : m_data(std::move(x)) {}
private:
void serialize(Storage& outStream) override
{ m_data.serialize(outStream); }
private:
T m_data;
};
template <typename T>
class Serializable::Model<T, false> final : public Serializable::Concept
{
public:
Model(T x) : m_data(std::move(x)) {}
private:
void serialize(Storage& outStream) override
{ serialize(m_data, outStream); }
private:
T m_data;
};
How would generic accessors for a property class and their defaults be implemented?
I roughly think it would look as follows:
template<typename Type,
typename Getter = /* How to implement a default setter? */
typename Setter =
class Property {
Getter get; /* Is this right? How is it called then? */
Setter set;
Property(Type value, Getter getter, Setter setter) ...
};
Getter and Setter should be able to be given as lambdas. Is this the right approach, and how do I continue?
You could agree to some kind of structural interface for getters and setters, and then implement something like this:
template <typename T> struct default_getter
{
T & operator()(T & x) const { return x; }
T const & operator()(T const & x) const { return x; }
};
template <typename T> struct default_setter
{
template <typename U>
void operator()(T & x, U && u) const { x = std::forward<U>(u); }
};
template <typename T,
typename Getter = default_getter<T>,
typename Setter = default_setter<T>>
class Property
{
struct PropertyImpl : Getter, Setter
{
T value;
};
PropertyImpl impl;
public:
template <typename U>
void set(U && u)
{
static_cast<Setter &>(impl)(impl.value, std::forward<U>(u));
}
T & get()
{
static_cast<Getter &>(impl)(impl.value);
}
T const & get() const
{
static_cast<Getter const &>(impl)(impl.value);
}
};
Now you can use it like so:
struct Foo
{
Property<Bar> bar;
};
Foo x;
x.bar.get();
x.bar.set(10);
I would propose a solution using std::function.
template<typename T>
struct Property
{
typedef std::function<T()> GetterFunc;
typedef std::function<void(const T&)> SetterFunc;
Property (T value, GetterFunc getter, SetterFunc setter)
: m_getter(getter)
, m_setter(setter)
{
}
Property(T value)
: m_getter( [value](){ return value; }
, m_setter ( [](const T&) { } ) // I have know clue what behaviour you want here
{
}
T Get() { return m_getter(); }
void Set(const T& value) { m_setter(value); }
private:
GetterFunc m_getter;
SetterFunc m_setter;
}