I have a data type OperationSequence. Below is OperationSequence.h
class OperationSequence
{
public:
void appendOperation(std::function<double(double)> operation);
void moveOperation(int operation_index);
void eraseOperation(int operation_index);
const std::vector<std::function<double(double)>>& data() const;
private:
std::vector<std::function<double(double)>> operation_sequence;
};
double executeSequence(const OperationSequence& operation_sequence, double value);
void executeSequence(const OperationSequence& operation_sequence, const std::string& file_name);
I have to implement printOperationSequence(const OperationSequence& operation_sequence).
Assignment set a requirement on operation to be f: double -> double. Some operations like Addition and Multiplication were also requested.
Obvious implementation would be to create an Interface Operation and have it be callable with f: double -> double and have a std::string getName() method.
What would be a good way for OperationSequence to remain this generic but also making it easy and efficient to print out OperationSequence in a meaningful way?
Meaningful way being something like Multiplication, Addition, ...
Is delegating construction to some other class that will also create a operation_name_sequence a good idea?
P.S. Feel free to improve the question title :D
If you want to avoid to have polymorphism (even if std::function uses it or similar for type erasure), you might create class Operation to add name to the function:
struct Operation
{
std::string name;
std::function<double(double)> f;
};
class OperationSequence
{
public:
void appendOperation(const Operation& operation);
void appendOperation(const std::string& name, std::function<double(double)> f);
void moveOperation(int operation_index);
void eraseOperation(int operation_index);
const std::vector<Operation>& data() const;
private:
std::vector<Operation> operations;
};
then
void printOperationSequence(const OperationSequence& operation_sequence)
{
for (const auto& op : operation_sequence.data()) {
std::cout << op.name << std::endl;
}
}
Related
I was wondering if using the std::move() in this example is overkill or computationally more expensive than simply copying it? I would really like to know.
class Student
{
private:
std::string _studentName;
int _studentGrade;
public:
Student() : _studentName("No Name"), _studentGrade(0) {}
std::string Name() const { return _studentName; }
void Name(std::string x) { _studentName = std::move(x); }
int Grade() const { return _studentGrade; }
void Grade(int x) { _studentGrade = std::move(x); }
};
Reading the core guidelines at F.call: Parameter passing, we can deduce a few recommendations.
Use move only when you want to optimize for rvalue. If you find that it does an improvement on performance, it's up to you to do it.
You could receive by value then move as it optimises rvalues calls into your setters, but it pessimizes lvalues. This is because std::string will reuse its storage and not cause unnecessary allocations when copying from the const reference. Copying into the value parameter always end up allocating when no SSO is possible.
The preferred way, especially for setters are to use const reference, and add an rvalue reference overload when rvalues are passed into the setter:
class Student
{
private:
std::string _studentName;
int _studentGrade;
public:
Student() : _studentName("No Name"), _studentGrade(0) {}
std::string_view Name() const { return _studentName; }
void Name(std::string const& x) { _studentName = x; }
// add this when you need to optimize for rvalues.
// optimizing for rvalues is not always needed.
// They can speedup quite a bit when actually needed.
void Name(std::string&& x) { _studentName = std::move(x); }
// int is a trivial type, so move does nothing. No move needed.
int Grade() const { return _studentGrade; }
void Grade(int x) { _studentGrade = x; }
}
For the int, std::move won't do anything, it's still a copy. Just take them by value and return them by value.
However, the best you can do is much simpler:
class Student
{
public:
std::string studentName;
int studentGrade;
};
Since your setters don't enforce any invariants, you'd be better off using public members. You don't need overloads and reference since std::string implements it for you.
I have an algorithm (not preseted here) which takes as input different parameters (int, float, vectors).
My idea of design was to have an container which holds all these differents parameters.
To achive this, I have a base class Parameter and a derivated template class TypeParameter.
These parameters will be holded in a container.
The design is presented below:
#pragma once
#include <utility>
#include <memory>
#include <string>
#include <vector>
namespace parameter
{
/*
Interface for parameter
*/
class Parameter
{
public:
Parameter() {}
Parameter(std::string param_name) : name(param_name) {}
Parameter(const Parameter&& other) noexcept : name(std::move(other.name)) {}
virtual ~Parameter() {}
inline const std::string get_name() { return name; }
private:
std::string name;
};
/*
*/
template<class T>
class TypeParameter
: public Parameter
{
public:
TypeParameter(std::string param_name, T new_value) : Parameter(param_name), value(new_value) {}
TypeParameter(const TypeParameter&& other) noexcept : Parameter(std::move(other)), value(std::move(other.T)) {}
inline const T get_value() { return value; }
private:
T value;
};
/*
Container for parameters
*/
class ParameterSet
{
public:
ParameterSet() {}
void add(std::unique_ptr<Parameter> param) { data.push_back(std::move(param)); }
private:
std::vector <std::unique_ptr<Parameter>> data;
};
} //namespace parameter
The main is:
#include <iostream>
#include <string>
#include "Parameter.h"
using parameter::TypeParameter;
using parameter::Parameter;
using parameter::ParameterSet;
void foo(std::unique_ptr<Parameter> p)
{
std::cout << p->get_value(); // ERROR
}
int main(int argc, char *argv[])
{
TypeParameter<int> *iparam = new TypeParameter<int>("ee", 3);
std::unique_ptr<Parameter> p = std::make_unique <TypeParameter<int>>("foo", 3);
foo(std::move(p));
ParameterSet param_set;
param_set.add(std::unique_ptr<Parameter>(iparam));
param_set.add(std::move(p));
getchar();
}
My problem is I cannot get the value without a cast.
Hence, my question is how do I cast the unique_ptr from a Parameter class to derived TypeParameter.
Is there another way to design the container?
Thanks a lot!
You don't have to reinvent the wheel. There are a couple of classes you can use from the standard library:
std::variant.
As suggested by the comments, variant is a type-safe union of a pre-defined set of data types, which you put in the templates argument of variant.
For example, a std::variant<int,float,double> can hold any value of type int, float, or double, but nothing else.
To use the stored value, you can either use the visitor pattern with the std::visit() function. Other functions allow you to know which of the preset types is stored in the variable (index()) and to extract the value from it (using get()). If you try to extract the value of the wrong type, the get() function throws an exception
std::any
is another utility that can hold different data types. As opposed to variant, you don't have to know the types at compile-time. Basically, it stores a void* to the data with a typeinfo to remember its original type. You can then use any_cast to cast the variable back to its original type. Just like variant, an exception is thrown when trying to cast to the wrong type.
These two classes are available in C++ 17. If these features are not available to you, they were also included in boost (respectively boost:variant and boost:any)
You can store the set of values in a standard library container, e.g. in a std::vector<std::variant<int,float,double>> or a std::vector<std::any>>.
Alternative to std::variant/std::any is the old way polymorphism:
class Parameter
{
public:
Parameter(const std::string& param_name) : name(param_name) {}
virtual ~Parameter() = default;
const std::string& get_name() const { return name; }
virtual void printValue() const = 0;
// Other virtual methods
private:
std::string name;
};
template<class T>
class TypeParameter : public Parameter
{
public:
TypeParameter(const std::string& name, const T& t) : Parameter(name), value(t) {}
// Non virtual method when we don't access it by base class.
const T& get_value() const { return value; }
void printValue() const { std::cout << value; }
private:
T value;
};
And then your
void foo(const Parameter& p)
{
std::cout << p.get_value(); // ERROR
}
becomes
void foo(const Parameter& p)
{
p.print();
}
If you don't want to add many virtual methods to Parameter, then Visitor pattern can help, but then you have to know each derived types.
I have an application which creates simple music visualization animations. These animations are driven by nodes, and each node has a bunch of parameters that could have one of several types: int, float, color, etc. The parameters can either have a user-set value, or can be connected to the output of another node.
I'm currently using a templated type, along with std::function<>, like this:
#include <functional>
template <class PT>
class Param
{
public:
Param(PT value=PT()) : _value(value), _provider(nullptr) {}
void setValue(const PT &value) {_value = value;}
void setProvider(std::function<void(PT&)> provider) {_provider = provider;}
void getCurrentValue(PT &value) {
// update current member value
if (_provider)
_provider(_value);
value = _value;
}
private:
PT _value;
std::function<void(PT &value)> _provider;
};
I then instantiate parameters for an animated nodes like this:
class AnimationNode
{
public:
AnimationNode(Model *model = nullptr);
void evaluate();
private:
Param<int> _xoffset;
Param<int> _yoffset;
Param<float> _scale;
Param<ColorType> _color;
};
These parameters could be connected to a driver node, such as this one:
class SublevelMeter {
public:
SublevelMeter();
void setRange(Subrange &_range);
...
std::function<void(float&)> createProviderClosure();
private:
float _level;
...
}
std::function<void(float&)> SublevelMeter::createProviderClosure() {
return [this] (float &out) {out = _level;};
}
And connect one node to another by doing something like this:
AnimationNode::connectScaleToSublevel(SublevelMeter *slm) {
_scale->setProvider(slm->createProviderClosure());
}
The problem is, I'd like there to be an abstract Param type that I can pass to objects, so rather than the code above, I could pass a param to my SublevelMeter:
SublevelMeter::connectToParam(Param *param) {
param->setProvider(slm->createProviderClosure());
}
This would also help when writing the routines that create my GUI editor widgets: the editor could figure out the correct type by introspection of the Param.
But I'm not sure how to do this from a templated class, nor how the best way to implement the introspection in C++. (I'm coming at this from a python design background, which is perhaps encouraging me to think about this in a pythonic rather than C++ way; if there's a better way to approach this, I'd love to hear about it!)
I'm using Qt, so I've considered using QVariant, or other Qt Meta-Object stuff, but I'm not sure how to make that work, or if it would even be appropriate. (I'm not using Boost, and while I know it has certain type erasure facilities, I'm wary of wading into those waters...)
I'm interested in what the cleanest/"best" way to do this. Although efficiency is a consideration (getCurrentValue() is called many times per frame while the animation is playing) I can still probably afford run-time overhead of dynamic type stuff.
At least the first part of your question is solvable without abstract Param:
class SublevelMeter {
...
template<class PT>
void connectToParam(Param<PT> *param) {
param->setProvider(createProviderClosure<PT>());
}
// specialize this for different PTs
template<class PT>
std::function<void(PT&)> createProviderClosure();
}
If you really need to manipulate dynamic lists of Param-s, and you don't want to use any kind of RTTI, consider using Visitor pattern:
class Visitor;
class ParamBase
{
public:
virtual ~ParamBase() = default;
virtual void acceptVisitor(Visitor* v) = 0;
};
template <class PT>
class Param : public ParamBase
{
public:
...
void acceptVisitor(Visitor* v) override;
};
class Visitor {
public:
virtual ~Visitor() = default;
void visit(ParamBase* p) {
p->acceptVisitor(this);
}
virtual void visitParam(Param<float>* p) = 0;
// add more functions for other Params
};
class PrintVisitor : public Visitor {
public:
void visitParam(Param<float>* p) override {
std::cout << "visited Param<float>, value = " << p->getValue() << std::endl;
}
};
template<class PT>
void Param<PT>::acceptVisitor(Visitor* v) {
v->visitParam(this);
}
int main() {
std::unique_ptr<ParamBase> p(new Param<float>(123.4f));
std::unique_ptr<Visitor> v(new PrintVisitor());
v->visit(p.get());
return 0;
}
I implemented for you a simple class for the generic type management. This class is implemented without using template, so you can declare your variables and assign a value and a type directly at runtime. This implementation is very simple you should use it as reference to develop your own solution. In the following example I implemented the support for only 3 types: int, double and char* (C string). The main function shows you as to use the generic type class for both LVALUE and RVALUE assignment:
#include <stdio.h>
#include <stdlib.h>
enum Types {tInteger, tDouble, tString};
class TGenericType
{
private:
char m_Value[100];
Types m_Type;
protected:
public:
void operator=(int AValue)
{
m_Type = tInteger;
sprintf(m_Value, "%d", AValue);
}
operator int()
{
// try to convert the m_Value in integer
return atoi(m_Value); // the result depend by atoi() function
}
void operator=(double AValue)
{
m_Type = tDouble;
sprintf(m_Value, "%f", AValue);
}
operator double()
{
// try to convert the m_Value in double
return atof(m_Value); // the result depends by atof() function
}
void operator=(char* AValue)
{
m_Type = tString;
strcpy(m_Value, AValue);
}
operator char*()
{
return m_Value;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
TGenericType LVar;
// int assignment LVar used as LVALUE
LVar = 10;
// int assignment LVar used as RVALUE
int i = LVar;
// Double assignment LVar used as LValue
LVar = 10.1;
// double assignment LVar used as RVALUE
double d = LVar;
// costant string assignment LVar used as RVALUE
LVar = "Ciao Mondo";
// string copying LVar used as const string RVALUE
char Buffer[100];
strcpy(Buffer, LVar);
return 0;
}
I tested above code on c++builder 32bit and c++builder (CLang) 64bit
If my solution answer your question, please check it as answered.
Ciao from Italy!
Angelo
I'd like to map string to an instance member functions, and store each mapping in the map.
What is the clean way of doing something like that?
class MyClass
{
//........
virtual double GetX();
virtual double GetSomethingElse();
virtual double GetT();
virtual double GetRR();
//........
};
class Processor
{
private:
typedef double (MyClass::*MemFuncGetter)();
static map<std::string, MemFuncGetter> descrToFuncMap;
public:
static void Initialize();
void Process(Myclass m, string);
};
void Processor::Initialize()
{
descrToFuncMap["X"]=&MyClass::GetX;
descrToFuncMap["SomethingElse"]=&MyClass::GetSomethingElse;
descrToFuncMap["RR"]=&MyClass::GetRR;
descrToFuncMap["T"]=&MyClass::GetT;
};
void Processor::Process(MyClass ms, const std::string& key)
{
map<std::string, Getter>::iterator found=descrToFuncMap.find(key);
if(found!=descrToFuncMap.end())
{
MemFuncGetter memFunc=found->second;
double dResult=(ms).*memFunc();
std::cout<<"Command="<<key<<", and result="<<result<<std::end;
}
}
let me know if you see a problem with this approach and what are common idioms for that?
Perhaps, I should use if-else-if statement chain, given that I have a limited number of member functions, instead of a confusing map of func pointers
BTW, I found some of the useful info here in the c++-faq-lite
Looks fine to me, but for the fact that descrToFuncMap needs to be declared static if you intend to initialise it from inside the static function Initialize().
If you want to make sure that Initialize() gets called, and gets called just once, you can use the Singleton pattern. Basically, if you aren't doing multithreading, that just means wrapping descrToFuncMap inside its own class (called say FuncMap) with a private constructor that calls Initialize(). Then you add a static local variable of type FuncMap to Processor::Process() -- because the variable is static, it persists and is only initialised once.
Example code (I now realise that friend isn't really necessary here):
class Processor {
private:
typedef double (MyClass::*MemFuncGetter)();
class FuncMap {
public:
FuncMap() {
descrToFuncMap["X"]=&MyClass::GetX;
descrToFuncMap["SomethingElse"]=&MyClass::GetSomethingElse;
descrToFuncMap["RR"]=&MyClass::GetRR;
descrToFuncMap["T"]=&MyClass::GetT;
}
// Of course you could encapsulate this, but its hardly worth
// the bother since the whole class is private anyway.
map<std::string, MemFuncGetter> descrToFuncMap;
};
public:
void Process(Myclass m, string);
};
void Processor::Process(MyClass ms, const std::string& key) {
static FuncMap fm; // Only gets initialised on first call
map<std::string, Getter>::iterator found=fm.descrToFuncMap.find(key);
if(found!=fm.descrToFuncMap.end()) {
MemFuncGetter memFunc=found->second;
double dResult=(ms).*memFunc();
std::cout<<"Command="<<key<<", and result="<<result<<std::end;
}
}
This is not the "true" Singleton pattern as different functions could create their own, separate instances of FuncMap, but it's enough for what you need. For "true" Singleton, you would declare FuncMap's constructor private and add a static method, say getInstance(), which defined the one-and-only instance as a static variable and returned a reference to that. Processor::Process() would then use this with
FuncMap& fm = FuncMap::getInstance();
I'd change
void Processor::Process(MyClass ms, std::string key)
to
void Processor::Process(const MyClass& ms, const std::string& key)
Don't see any bad side effect for now. Probably with boost::function as a map value it will be easier in the future.
Avoid using 'virtual' if you are using maps of function pointers. In this context, using 'virtual' keyword will not help much. For example
descrToFuncMap["X"]=&MyClass::GetX;
will always call 'MyClass::GetX' function even if GetX is overridden by the derived class of MyClass.
Usually you won't have large number of functions in class, rather than using map you can create simple struct array and use a for loop. If the number of functions are small, there won't be any big performance difference in map and array. Something similar to code below will work
class MyClass
{
//........
double GetX();
double GetSomethingElse();
double GetT();
double GetRR();
//........
};
typedef double (MyClass::*MemFuncGetter)();
struct FuncTable
{
const char* m_pFuncName;
MemFuncGetter m_pFuncPtr;
};
class Processor
{
public:
void Process(Myclass& m, string);
};
static FuncTable descrToFuncMap[]
{
{ "X", &MyClass::GetX},
{ "SomethingElse", &MyClass::GetSomethingElse },
{ "RR", &MyClass::GetRR},
{ "T", &MyClass::GetT}
};
void Processor::Process(MyClass& ms, const std::string& key)
{
int functablesize = sizeof(descrToFuncMap)/sizeof(descrToFuncMap[0])
for(int i=0; i< functablesize; ++i)
{
if( strcmp(key.c_str(), descrToFuncMap[i].m_pFuncName)==0)
{
MemFuncGetter memFunc=descrToFuncMap[i].m_pFuncPtr;
double dResult=(ms).*memFunc();
std::cout<<"Command="<<key<<"result="<<result<<std::end;
break;
}
}
}
i was wondering if there was a way to do this in C++?
void func1(const std::string& s)
{
std::cout << s << std::endl;
}
void func2(int me)
{
std::cout << me << std::endl;
}
int main()
{
std::map<std::string, boost::function< ??? > > a_map;
a_map["func1"] = &func1;
a_map["func1"]("HELLO");
}
Is there any way to do what i have above using boost function and a map?
There are ways to store the functions, the problem is, in order to be able to call the function with the desired argument you'd have to know the calling signature of the function anyways, and if you have that information, you might as well use separate maps, or use a more complicated object than boost::function.
If you're willing to do a bit of work and have a finite number of signatures, you could just do something like this:
class MultiFunc
{
protected:
MultiFunc() {}
public:
typedef void (*stringFunc)(const std::string&);
typedef void (*intFunc)(int);
static MultiFunc *Create(stringFunc function);
static MultiFunc *Create(intFunc function);
virtual void operator()(const string &) { throw exception(); }
virtual void operator()(int) { throw exception(); }
virtual ~MultiFunc();
};
class MultiFuncString : public MultiFunc
{
private:
stringFunc Function;
public:
MultiFuncString(stringFunc function) : Function(function) {}
virtual void operator()(const string &arg) { Function(arg); }
};
class MultiFuncInt : public MultiFunc
{
private:
intFunc Function;
public:
MultiFuncInt(intFunc function) : Function(function) {}
virtual void operator()(int arg) { Function(arg); }
};
MultiFunc *MultiFunc::Create(MultiFunc::stringFunc function)
{
return new MultiFuncString(function);
}
MultiFunc *MultiFunc::Create(MultiFunc::intFunc function)
{
return new MultiFuncInt(function);
}
void func1(const std::string& s)
{
std::cout << s << std::endl;
}
void func2(int me)
{
std::cout << me << std::endl;
}
int main()
{
map<string, MultiFunc *> a_map;
a_map["func1"] = MultiFunc::Create(&func1);
(*a_map["func1"])("Hello");
a_map["func2"] = MultiFunc::Create(&func2);
(*a_map["func2"])(3);
// Remember to delete the MultiFunc object, or use smart pointers.
}
This outputs:
Hello
3
Unfortunately, you can't make templated virtual functions or you easily generalize this all.
You probably can't use the std::map since it is a homogenous container. Try, something like boost::variant (they support the visitor pattern) or boost::tuple
What you are trying to do sounds a little weird. Normally, you would have a container be a collection of abstract types or objects or functions with the same signature. Otherwise, how would you know how to call the function when you are iterating the container? I like to make the container a collection of function objects with a known signature, then use Boost.Bind to store closures that call the function with additional arguments.
For example:
typedef boost::function<void, void> Function;
typedef std::map<std::string, Function> Functions;
Functions functions:
void foo()
{
...
}
functions["foo"] = foo;
void bar(std::string &s)
{
...
}
// binds the value "hello" to the s parameter
functions["bar"] = boost::bind(bar, "hello");
read this link below. It talks about using boost::bind to store the function pointers in std::map
http://www.gamedev.net/community/forums/topic.asp?topic_id=526381&whichpage=1�
store interfaces:
struct IStringData
{
virtual std::string get() const = 0;
virtual ~IStringData() {}
};
and make implementaions, one will just hold string value, other implementation will store functor, maybe you will have other implementations in future.
No. You can't. Since boost::function isn't polymorphic, it breaks down there. (It takes a fixed set of argument types.)
There was talk about work in that direction on the boost mail-list, though, so search the archives and see if there is some code you could youse.
A workaround would be to use boost::function but then you need to add to the map not your real functions (i.e. func1/func2) but dispatch functions that extracts the type from the any-container and calls the real function. (And bails if it's wrong, just as in any dynamic langugage.)