I have an Interface (there missing a lot of members, but mind the fact this interface is mandatory). I will need 5 classes inheriting from it, which will have a _value attribute. So, ins\
tead of implement 5 classes(for char, short, int, float, double), I thought about a template class :
class my_interface
{
public:
virtual [various_types] getValue() const = 0;
};
template<typename T>
class my_class : public my_interface
{
private:
T _value;
public:
my_class(T value) : _value(value) {} // initialize the attribute on construct
virtual T getValue() const { return _value; }
};
...so that something like that could work :
void my_function()
{
my_inteface* a = new my_class<char>(42);
my_interace* b = new my_class<short>(21);
int result;
result = a->getValue() + b->getValue();
}
But I don't see how I could do. It seems you can't make templates on interface pure virtual. To me, the only way that could work would be to make getValue() to always return a double, since it is the highest sized type I need. However, I don't like that solution.
If you have just one methods (getValue()) on your interface then you only need the template class implementation.
However if you want to an interface like this:
std::string getValue();
int getValue();
long getValue();
Then you are out of luck as you cannot overload a function name based only on the return type. Alternatively you could create a wrapper type.
EDIT
By wrapper type what I mean is that if getValue is required to return multiple types you could do it in a number of ways using a wrapper class that encapsulates your required functionality rather than add it to your top level interface. It could look something like this:
enum ValType{
INT, CHAR, STR, DEQUE
};
class Wrapper{
private:
union S{
int intVal;
char charVal;
std::string stringVal;
std::deque dequeVal;
~S() {}
} theVal;
ValType heldType;
public:
void setVal(int value){ heldType = INT; theVal.intVal = value; }
void setVal(char value){ heldType = CHAR; theVal.charVal = value; }
// ... and so on
int getIntVal() const {
if(heldType!=INT)
throw std::runtime_error("Cop on");
return theVal.int;
}
// and so on
}
Then your interface is
public class my_interface{
virtual Wrapper getVal();
}
You are not really gaining much here as the user will still have to call the correct child member of Wrapper.
You could also just represent the return values as a string if you wanted.
Note that using unions you need to be careful of the caveats:
http://en.cppreference.com/w/cpp/language/union
EDIT 2:
You could do this with a templated return
template<typename = T>
const T& getVal(const T& typeToAllowMethodOverriding) const;
Remember that 'virtual ...' means "make a function pointer in the class that I will use to call the correct derived class". It is just a pointer -- so you have to agree on the return type before you call it. C++ doesn't have the dynamic types and reflection of other languages - it has to know what the return type is before making the call.
You could make class my_interface a template class as well:
template<typename T>
class my_interface
{
public:
virtual T getValue() const = 0;
};
This will generate an interface and a class for every type T that you use.
template<typename U>
class my_interface
{
public:
virtual U getValue() const = 0;
};
template<typename T>
class my_class : public my_interface<T>
{
private:
T _value;
public:
my_class(T value) : _value(value) {} // initialize the attribute on construct
T getValue() const { return _value; }
};
It works for all types but for string type you have to do specialization of templates
I think your best shot will be to use/implement something like boost::variant.
typedef boost::variant<char, short, int, float, double> Value;
class my_interface
{
public:
virtual Value getValue() const = 0;
};
template<typename T>
class my_class : public my_interface
{
private:
T _value;
public:
my_class(T value) : _value(value) {} // initialize the attribute on construct
virtual Value getValue() const { return _value; }
};
Then you could implement the arithmetic operators:
Value operator+(const Value &lhs, const Value &rhs) {
//Check the internal types of lhs and rhs and perform the operation
}
You can also wrap the boost::variant in another class, to provide conversion operators to the basic types.
Related
How do I ensure my derived class implements at least one of two chosen methods in the base class?
class base {
public:
virtual int sample()=0;
virtual Eigen::VectorXf sample()=0;
};
class Derived : Base {
int sample() override {return 1;}
}
This code returns an error, as the sample method is not implemented with the VectorXf return type. However, my intention is that only one of these need to be implemented. The only reason they are seperate in the base class is that they have different return type. How can I do this in C++?
Overloading by return type is not possible. You may use std::variant instead:
#include <variant>
class Base {
public:
virtual std::variant<int, Eigen::VectorXf> sample()=0;
};
class Derived : public Base {
std::variant<int, Eigen::VectorXf> sample() override {return 1;}
};
If one is restricted to C++11, then there are many alternatives.
Implement and use something like variant: a class that has a enumerator selecting between two active types, and a union to contain these types.
Use Boost variant.
std::pair
Implement a hierarchy of classes (a simplification of std::any), and return on the right pointer to object:
class AbstractBase {
public:
virtual ~AbstractBase() = 0;
template <class T>
const T* get() const;
};
template <class T>
class ValueWrapper : public AbstractBase {
public:
ValueWrapper(const T& value) : m_value(value) {}
const T & getValue() const { return m_value; }
private:
T m_value;
};
template <class T>
inline const T * AbstractBase::get() const {
auto child = dynamic_cast<ValueWrapper<T> const*>(this);
return child ? &child->getValue() : nullptr;
}
class Base {
public:
virtual std::unique_ptr<AbstractBase> sample()=0;
};
The question is, why would you need this?
I want to enhance members of C++ classes so that assignment from/to them results in the call of a custom getter/setter.
Like
class Class
{
public:
int Member;
void SetMember(int Value); // TBD
int GetMember(); // TBD
}
and
Class Instance;
Instance.Member= 3; // Causes a call to SetMember(3);
int Data= Instance.Member; // Causes a call to GetMember();
I have found a way to force a function call upon member assignment, by turning the member type to a class holding a private value, and overloading the cast operator for reading and the assignment operator for writing.
class WrapInt
{
public:
operator int() const { return Value; }
void operator=(const int Assign) { Value= Assign; }
private:
int Value;
}
This works, but in a generic way, I cannot customize the getters/setters per member but only per data type.
Do you see a way to refine so that I can write different accessors for different members of the same type ?
Update:
I have now found a solution that satisfies my needs. The members that require a special setter are defined using a class that knows the hosting class:
template<class Parent> class WrapInt
{
public:
int operator=(const int Value) { (This->*Setter)(Value); return Value; }
operator int() { return Value; }
private:
int Value;
Parent* This;
void (Parent::*Setter)(int Value);
friend Parent;
};
Assigning such a member invokes the assignment operator, which calls a plain setter function via a pointer to method of the main class. The Get operation is implemented via the cast operator, which just returns the member value (the scheme might be enhanced to support custom getters, but I didn't need that).
This is pretty costly as every member takes an extra This pointer to the class instance and a pointer to the setter; these need to be initialized in the class constructor (if not, a crash is guaranteed).
So this takes some effort on the side of the class writer (initialization in the constructor), but then assigning to the member automatically invokes the setter, as I want.
class Class
{
public:
Class();
WrapInt<Class> Member;
private:
void SetMember(int Value); // TBD
}
Class::Class() { Member.This= this; Member.Setter= &Class::SetMember; }
On the side of the user,
Class Instance;
Instance.Member= 3; // Calls the setter SetMember
cout << Instance.Member;
that's it.
You could make your class WrapInt modifyable.
Option 1: At runtime, using a function object
class WrapInt
{
public:
operator int() const { return Value; }
void operator=(const int Assign)
{
assign_callback(Assign);
Value = Assign;
}
private:
int Value;
std::function<void (int)> assign_callback;
}
In this variant, you would have to assign the correct callbacks in the constructor of the containing class:
class Container
{
WrapInt a, b, c;
Container ()
{
a.assign_callback = ...;
b.assign_callback = ...;
c.assign_callback = ...;
}
}
Option 2: At compile-time, using inheritance
class WrapInt
{
public:
operator int() const { return Value; }
void operator=(const int Assign)
{
assign_callback(Assign);
Value = Assign;
}
private:
int Value;
virtual void assign_callback(int) = 0;
}
In this variant, you would inherit from WrapInt multiple times in the class body of the containing class
class Container
{
class WrapIntA : public WrapInt {
void assign_callback() { ... };
} a;
class WrapIntB : public WrapInt {
void assign_callback() { ... };
} b;
class WrapIntC : public WrapInt {
void assign_callback() { ... };
} c;
}
A modified version of your code:
class WrapInt
{
public:
WrapInt(std::function<int()> getter, std::function<void(int)> setter) :
getter(getter),
setter(setter)
{}
WrapInt(const WrapInt&) = delete;
WrapInt& operator =(const WrapInt&) = delete;
operator int() const { return getter(); }
void operator=(int value) { setter(value); }
private:
std::function<int()> getter;
std::function<void(int)> setter;
};
class Class
{
public:
Class() : Member([this](){ return this->GetMember();},
[this](int value) {SetMember(value); })
{}
WrapInt Member;
void SetMember(int Value); // TBD
int GetMember(); // TBD
};
Don't fight the language: C++ does not support get / set bindings to functions. You merely have to tolerate
Instance.Member() = 3;
and
int Data = Instance.Member();
Which you can provide by supplying a const function Member() that returns a const reference, and a non-const version that returns a non-const reference.
One criticism of C++ is the amount of boilerplate you need to write, especially if you need this for every member variable in your class. But really at that point, you are pretty much circumventing encapsulation entirely: you may as well make the members public unless your functions make consistency checks.
I am trying to solve a programming problem that consists of an object (call it Diagram), that contains several parameters. Each parameter (the Parameter class) can be one of several types: int, double, complex, string - to name a few.
So my first instinct was to define my Diagram class as having a vector of template parameters, which would look like this.
class Diagram
{
private:
std::vector<Parameter<T> > v;
};
This doesn't compile, and I understand why. So, based on the recommendations on this page How to declare data members that are objects of any type in a class, I modified my code to look like:
class ParameterBase
{
public:
virtual void setValue() = 0;
virtual ~ParameterBase() { }
};
template <typename T>
class Parameter : public ParameterBase
{
public:
void setValue() // I want this to be
// void setValue(const T & val)
{
// I want this to be
// value = val;
}
private:
T value;
};
class Diagram
{
public:
std::vector<ParameterBase *> v;
int type;
};
I'm having trouble figuring out how to call the setValue function with an appropriate templated parameter. It is not possible to have a templated parameter in the ParameterBase abstract base class. Any help is greatly appreciated.
P.S. I don't have the flexibility to use boost::any.
You got very close. I added a few bits because they're handy
class ParameterBase
{
public:
virtual ~ParameterBase() {}
template<class T> const T& get() const; //to be implimented after Parameter
template<class T, class U> void setValue(const U& rhs); //to be implimented after Parameter
};
template <typename T>
class Parameter : public ParameterBase
{
public:
Parameter(const T& rhs) :value(rhs) {}
const T& get() const {return value;}
void setValue(const T& rhs) {value=rhs;}
private:
T value;
};
//Here's the trick: dynamic_cast rather than virtual
template<class T> const T& ParameterBase::get() const
{ return dynamic_cast<const Parameter<T>&>(*this).get(); }
template<class T, class U> void ParameterBase::setValue(const U& rhs)
{ return dynamic_cast<Parameter<T>&>(*this).setValue(rhs); }
class Diagram
{
public:
std::vector<ParameterBase*> v;
int type;
};
Diagram can then do stuff like these:
Parameter<std::string> p1("Hello");
v.push_back(&p1);
std::cout << v[0]->get<std::string>(); //read the string
v[0]->set<std::string>("BANANA"); //set the string to something else
v[0]->get<int>(); //throws a std::bad_cast exception
It looks like your intent is to store resource-owning pointers in the vector. If so, be careful to make Diagram have the correct destructor, and make it non-copy-constructable, and non-copy-assignable.
The bellow implementation uses a few C++11 features but you will be
able to pick them apart.
#include <vector>
#include <memory>
class Parameter
{
private:
class ParameterBase {
public:
virtual ~ParameterBase() {}
virtual ParameterBase* copy() = 0;
virtual void foo() = 0;
};
template <typename T>
class ParameterModel : public ParameterBase {
public:
// take by value so we simply move twice, if movable
ParameterModel(const T& t) : t(t) {}
ParameterModel(T&& t) : t(t) {}
void foo() { t.foo(); }
ParameterModel* copy() { return new ParameterModel(*this); }
private:
T t;
};
public:
template <typename T>
Parameter(T&& t)
: pp(new ParameterModel< typename std::remove_reference<T>::type >(std::forward<T>(t))) {}
// Movable and Copyable only
Parameter(Parameter&&) = default;
Parameter& operator=(Parameter&&) = default;
Parameter(const Parameter& other) : pp(other.pp->copy()) {};
Parameter operator=(const Parameter& other) {
pp.reset(other.pp->copy());
return *this;
};
// members
void foo() { pp->foo(); }
private:
std::unique_ptr<ParameterBase> pp;
};
class Diagram
{
public:
std::vector<Parameter> v;
int type;
};
struct X {
void foo() {}
};
struct Y {
void foo() {}
};
int main()
{
Diagram d;
d.v.emplace_back(X()); // int
// parameters are copyable and can be reassigned even with different
// impls
Parameter p = d.v.back();
Parameter other((Y()));
other = p;
return 0;
}
What does this code do? It hides the fact that we use inheritance to
implement parameters from our users. All they should need to know is
that we require a member function called foo. These requirements are
expressed in our ParameterBase. You need to identify these
requirements and add the to ParameterBase. This is basically a more
restrictive boost::any.
It is also quite close to what is described in Sean Parent's value semantics talk.
Following does not work:
std::vector<IRule*> vec;
RuleRangeDouble *rule = new RuleRangeDouble(0, 100);
vec.push_back(rule);
Now how can a make a vector of different rules? I know, I have to use pointers... But what else do I have to do to get this working? How can I change my base structure to get this work?
I use an Interface like the following:
// Interface
template <typename T>
class IRule
{
public:
virtual bool isValid(T value) = 0;
};
And my example class looks like this:
class RuleRangeDouble : public IRule<double>
{
private:
double min;
double max;
public:
bool isValid(double value)
{
....
};
};
The vector needs to be a vector of an actual type, for example std::vector<IRule<double>*>. Irule on its own is not a type, it is a class template. So you would need
std::vector<IRule<double>*> vec;
RuleRangeDouble *rule = new RuleRangeDouble(0, 100);
vec.push_back(rule);
If the template parameter is not part of the interface, you can introduce a common base class. Don't forget to give it a virtual destructor:
class IRule
{
public:
virtual bool isValid(T value) = 0;
virtual ~IRule() {}
};
template <typename T>
class Rule : public IRule
{
.....
};
class RuleRangeDouble : public Rule<double>
{
....
};
Then your original use case sample would work:
std::vector<IRule*> vec; // IRule really is a type now
RuleRangeDouble *rule = new RuleRangeDouble(0, 100);
vec.push_back(rule);
You can implement something like getBestValidValue()in several ways. One is to define a special general (but non-template) return type to be used for getBestValidValue() and also as argument type for isValid(value) (juanchopanza's answer was faulty here):
class ValueType
{
enum { is_int, is_double } my_type; // add more if you want
union { my_int; my_double; }; // union only works for simple types
public:
// implicit construction from allowed types
ValueType(int x) : my_type(is_int), my_int(x) {}
ValueType(double x) : my_type(is_double), my_double(x) {}
// use SFINAE for is<type>() function
template<typename T>
typename std::enable_if<std::is_same<T,int>::value,bool>::type
is() const { return my_type==is_int; }
template<typename T>
typename std::enable_if<std::is_same<T,double>::value,bool>::type
is() const { return my_type==is_double; }
// implicit type conversion to allowed types
// note: does not assert(is<T>())
operator int() { return my_int; }
operator double() { return my_double; }
};
class IRule
{
public:
virtual bool isValid(ValueType const&) const = 0; // fixed bug in juanchopanza's answer
virtual ValueType getBestValidValue() const = 0; // return any type of value
virtual ~IRule() {}
};
template<typename T>
class Rule : public IRule
{
protected:
virtual bool valid(T) const = 0;
virtual T bestValidValue() const = 0;
public:
bool isValid(ValueType const&value) const
{
return value.is<T>()
&& valid(value); // implicit type conversion to T
}
ValueType getBestValidValue() const
{
return bestValidValue(); // implicit construction of ValueType
}
....
}
I'm trying to define a base a class in C++ that has pure virtual methods to be implemented by children classes.
I would like to define setter and getter functions for basic types in the base class, but I would like the derived class to be able to determine the basic type of the getter and setter. For instance my base class would look like this:
class Value
{
public:
Value();
template <class T>;
virtual T getValue() = 0;
virtual void setValue(T val) = 0;
}
and my child class would look something like this:
class IntValue : public Value
{
public:
IntValue();
template <class T>
T getValue() {return _val};
void setValue(T val) {_val = val};
private:
int _val;
}
Of course the above code does not work. Any ideas on how to achieve this? Thanks in advance.
If I understood your problem correctly, rewriting your code to
template <class T>
class Value
{
public:
Value();
virtual T getValue() = 0;
virtual void setValue(T val) = 0;
};
class IntValue : public Value<int>
{
public:
IntValue();
int getValue() {return _val;}
void setValue(int val) {_val = val;}
private:
int _val;
};
should work
What you're asking for is not possible. In order to generate the right entries in the vtbl (or whatever similar structure the compiler might be using), the compiler needs to know what entries are going to be needed in the base class specifically. You can't just return a different type in a derived class and expect the base class to "know" about it in that way; as that would require a modification of the definition of the function template in the base class.
An example of how you might do that kind of modification of the base class using a class template (rather than a function template) can be seen in J_D's answer, but that still doesn't match your problem description exactly, because you wouldn't be able to create a Value and treat it polymorphicly.
C++ templates are essentially "fancy-pants find and replace" with the type -- when the compiler instantiates the function template, it generates a plain function with the typenames replaced. Note that this is very different than C# or Java "generics", which are completely different and rely on runtime support and a layer of indirection to achieve a similar effect. (Note though that this "find and replace" respects precedence rules and such, unlike C preprocessor macros :) )
If you really think about it too, this pattern does not make sense. What would this really look like on the client side of things?
class Value
{
public:
Value();
//Imagine if this were possible...
template <class T>;
virtual T getValue() = 0;
virtual void setValue(T val) = 0;
}
class IntValue : public Value
{
public:
IntValue();
int getValue() {return _val};
void setValue(int val) {_val = val};
private:
int _val;
}
class FloatValue : public Value
{
public:
FloatValue();
float getValue() {return _val};
void setValue(float val) {_val = val};
private:
float _val;
}
Now, you go to use this class:
void example(Value * ptr)
{
//What could you possibly say the type of "bar" is? There's no type that works!
???? bar = ptr->getValue();
delete ptr;
}
int main()
{
example(new IntValue());
example(new FloatValue());
}
As such, even if this were allowed, it wouldn't make much sense. You'd always have to downcast all the time, which would mean that the virtual keyword would be meaningless anyway.
Expanding on what #Billy ONeal said about a class template, this may work for your purposes:
template<typename Type>
class Value
{
public:
virtual Type getValue() = 0;
};
class IntValue : public Value<int>
{
public:
IntValue(int value)
: m_value(value)
{
}
int getValue()
{
return m_value;
}
private:
int m_value;
};