Suppose we have code like this:
template<class CALLBACK>
struct INIFile{
INIFile(CALLBACK &processor) :
processor(processor ){}
bool process(){
// lots of code here,
// call processor
processor(123);
return true;
}
CALLBACK &processor;
};
struct MyProcessor{
void operator()(int val){
// do something
}
};
struct MyConstProcessor{
void operator()(int val) const{ // !!!!!
// do something
}
};
int main(){
MyProcessor p;
INIFile<MyProcessor> ini(p);
ini.process();
// const case:
MyConstProcessor cp;
INIFile<MyConstProcessor> cini(cp);
cini.process();
}
In both cases INIFile<>::process() will be a non const member function.
Is there an easy way to make process() a const member function if CALLBACK::operator() is const, without duplicate all logic in INIFile<>::process()?
Your problem is solved by doing the following:
template<class CALLBACK>
struct INIFile{
INIFile(CALLBACK &processor) :
processor(processor){}
template <class T>
bool process_impl(T& processor) const {
// deliberately shadow processor
// reduce likelihood of using member processor, but can use other member variables
// lots of code
processor(123);
return true;
}
bool process() const {
return process_impl(const_cast<const CALLBACK&>(processor));
}
bool process() {
return process_impl(processor);
}
CALLBACK& processor;
};
This of course technically overloads process, but it has the exact same effect that you want. If the processor's call operator is not marked const, and you try to call process via a const reference or const copy of the object, you get a compilation error (unlike with your solution). That's because the const overload of process gets called, it adds the const to the processor which gets passed along, and then of course the call operator on the processor fails.
However, if the callback does provide a const call operator, then either process call will do exactly the same thing. This effectively means that you can call process on a const copy of INIFile, which is equivalent to process being const.
If the callback also overloads the call operator, then this implementation will forward along to whichever is correct, but you didn't specify that as a condition. The only thing to watch out for, is that process_impl should never access the member variable processor, because that member variable will always be mutable, i.e. the call will work even when it shouldn't (like in your solution). I shadow intentionally to try to prevent this. This isn't that beautiful but as an implementation detail it's not so bad, and it does remove the duplication.
Another way I found, but I do not like it very much is to use pointer instead of reference.
Here is the code.
Note in this particular case we do not need to check for nullptr at all.
template<class CALLBACK>
struct INIFile{
INIFile(CALLBACK &processor) :
processor(& processor ){}
bool process() const{
// lots of code here,
// call processor
processor->operator()(123);
return true;
}
CALLBACK *processor;
};
Related
I have a class like this:
class factory;
using factory_ptr = std::unique_ptr<IComponent> (factory::*)() const noexcept;
class factory {
public:
factory();
~factory() = default;
std::unique_ptr<Chipset> &create(const std::string &type);
private:
template<class T>
std::unique_ptr<T> Tcreate() const noexcept;
std::map<std::string, factory_ptr> m_fac;
};
#include "factory.inl"
My template function Tcreate is just:
template<class T>
std::unique_ptr<T> factory::Tcreate() const noexcept {
return std::make_unique<T>();
}
And the other function are just:
factory::factory() {
m_fac.emplace("4001", &factory::Tcreate<chipset4001>);
m_fac.emplace("4008", &factory::Tcreate<chipset4008>);
m_fac.emplace("4011", &factory::Tcreate<chipset4011>);
m_fac.emplace("4030", &factory::Tcreate<chipset4030>);
m_fac.emplace("4069", &factory::Tcreate<chipset4069>);
m_fac.emplace("4071", &factory::Tcreate<chipset4071>);
m_fac.emplace("4081", &factory::Tcreate<chipset4081>);
m_fac.emplace("4512", &factory::Tcreate<chipset4512>);
}
std::unique_ptr<Chipset> &factory::create(const std::string &type) {
if (m_fac.find(type) == m_fac.end()) {
throw nts::exception("can't find the chipset: " + type, "FactoryCreate");
}
return (this->*(m_fac.find(type)->second))();
}
Every chipset like chipsetXXXX are a class like:
class chipsetXXXX : Chipset {}
What I want to do here with this code is to generate an std::unique_ptr<> of a certain chipset linked with a string (cf. factory::m_fac), but when I run it a lot of error message pop on my terminal (more than what my terminal can handle). but i can't figured out what go wrong with it.
The issue is that your Tcreate function does not have the required signature. You're trying to create a map of functions which return an std::unique_ptr<IComponent>, but Tcreate() returns std::unique_ptr<T>.
I'm assuming Chipset inherits from IComponent. And as you note each T inherits from Chipset. So the conversion from e.g. std::unique_ptr<chipset4001> to std::unique_ptr<IComponent> is certainly possible, but that doesn't mean that the signature matches. E.g. a pointer to a function double do_thing () can't be assigned to a function pointer expecting an int (*) ().
So the solution is to change the return type of Tcreate to std::unique_ptr<IComponent>:
template<class T>
std::unique_ptr<IComponent> factory::Tcreate() const noexcept {
return std::make_unique<T>();
}
However, when you do that, you'll now get a compile error in create(), because that tries to return an std::unique_ptr<Chipset>. It's up to you to decide what to do there. Either return std::unique_ptr<IComponent>, or change factory_ptr to be a pointer to a function returning std::unique_ptr<Chipset> (and of course change Tcreate() accordingly).
I am trying to implement lazy initializing in C++ and I am searching for a nice way to call the Initialize() member function when some other method like object->GetName() gets called.
Right now I have implemented it as follows:
class Person
{
protected:
bool initialized = false;
std::string name;
void Initialize()
{
name = "My name!"; // do heavy reading from database
initialized = true;
}
public:
std::string GetName()
{
if (!initialized) {
Initialize();
}
return name;
}
};
This does exactly what I need for the time being. But it is very tedious to setup the initialized check for every method, so I want to get rid of that. If someone knows a nice way in C++ to improve this above example, I would like to know!
Could maybe operators be used to achieve calling Initialize() when using -> for example?
Thanks!
Sounds like a job for templates! Create a lazily_initialized wrapper that takes a type T and a function object TInitializer type:
template <typename T, typename TInitializer>
class lazily_initialized : TInitializer
{// ^^^^^^^^^^^^^^
// inheritance used for empty-base optimization
private:
T _data;
bool _initialized = false;
public:
lazily_initialized(TInitializer init = {})
: TInitializer(std::move(init))
{
}
T& get()
{
if(!_initialized)
{
static_cast<TInitializer&>(*this)(_data);
_initialized = true;
}
return _data;
}
};
You can the use it as follows:
struct ReadFromDatabase
{
void operator()(std::string& target) const
{
std::cout << "initializing...\n";
target = "hello!";
}
};
struct Foo
{
lazily_initialized<std::string, ReadFromDatabase> _str;
};
Example:
int main()
{
Foo foo;
foo._str.get(); // prints "initializing...", returns "hello!"
foo._str.get(); // returns "hello!"
}
example on wandbox
As Jarod42 mentioned in the comments, std::optional<T> or boost::optional<T> should be used instead of a separate bool field in order to represent the "uninitialized state". This allows non default-constructible types to be used with lazily_initialized, and also makes the code more elegant and safer.
As the former requires C++17 and the latter requires boost, I used a separate bool field to make my answer as simple as possible. A real implementation should consider using optional, using noexcept where appropriate, and also consider exposing a const-qualified get() that returns a const T&.
Maybe call it in the constructor?
Edit: Uh, i missed the point of your question sorry.
What about a lazy factory initialization?
https://en.wikipedia.org/wiki/Lazy_initialization#C.2B.2B
I'm writing my own little game-engine.
To separate the option-menu from the main-menu and from the main-game and so on I thought of making a state-system, where everything mentioned above is an own state.
The engines main-loop calls a tick() method on the current State.
But now the engine knows nothing about interaction between the states, when to switch states and so on.
To address this problem I implemented the following:
the tick()-method of the states returns a template type: commandset.
The Engine gets an Eventhandler to handle the return value of the tick() - methods.
It looks like this:
template<class StateHandler, typename FeedbackType>
void Engine<StateHandler, FeedbackType>::run()
{
run = true;
clock.restart();
while (run)
{
sf::Time elapsed = clock.restart();
Win->clear(sf::Color::Black);
processEvents();
if (!pause)
{
Handler(currentState->tick(elapsed), *this);
if (overlayState != NULL)
Handler(overlayState->tick(elapsed), *this);
}
Win->display();
}
}
So, the engine calls the handler on the return value of tick, and passes itself to it. So that the Handler can interact with the engine. (The Variable Handler is of the type StateHandler)
And now when I wanted to test everything, and wrote a Teststate, and a handler, I ran into trouble.
For later uses I intended to use a class as handler, but for the simple test purpose I wanted to use a function.
So when I wanted to write the function, I noticed, that I can't define the second parameter, the engine, because its template argument would be the type of the function(which depends on the Engines type, which depends on the functions type ...).
And now my question: How can I define the Handler? Or is the whole idea garbage? (which would be really tragic, because I kinda like it)
Is a function so much less work that it's worth worrying over?
struct TestHandler {
void operator ()(const CommandSet& cs, Engine<TestHandler, TestFeedback>& e) {
}
};
If you really want a function, you have to jump through hoops. For perverse pleasure, I've added a way to make this work:
class any_ref {
public:
template <typename T>
any_ref(T& ref)
: pointer(&ref)
#if !defined(NDEBUG)
, type(&typeid(T))
#endif
{}
template <typename T>
T& get() const {
assert(typeid(T) == *type);
return *static_cast<T*>(pointer);
}
private:
void* pointer;
#if !defined(NDEBUG)
const std::type_info* type;
#endif
};
void TestHandler(const CommandSet& cs, any_ref er) {
auto& e = er.get<Engine<void (*)(const CommandSet&, any_ref), TestFeedback>>();
}
I have a method with the following definition:
void foo(int i = 0, bool flag = false) {}
I want to call foo() by passing only the second argument:
foo(true);
But like this it will always pass it to the first parameter (i).
Is there any other solution I can pass my argument to the second parameter ? Or the only way is to pass the first one also.
foo(0, true);
Technically no. But you can fake it with overloads, thusly:
void foo(bool flag)
{
foo(0,flag);
}
no. unlike python, you cannot explicitly state which parameter you want to have the value. you will have to call the method with all the parameters if you need the last one to be not the default.
It's not possible in C++, since it doesn't support named parameters: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.20
However you may use overloading:
void foo(int i, bool flag) {
//do stuff
}
inline void foo(int i) { foo(i, false); }
inline void foo(bool flag) { foo(0, flag); }
int main(void) {
foo(42);
foo(true);
return 0;
}
The former would include the base implementation and gets called by the latter ones.
Notice how they're inline.
No, when you want to pass only one parameter, you will pass the first. How the compiler could guess which parameter do you intend to use?
There's a nice "trick" called the named parameter idiom : http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.20
Here's a rough way you'd implement it for your code.
(Though its really only useful for cases where there's a lot more default/optional arguments)
class Foo
{
public:
//set the defaults
Foo():i_(100),flag_(false) {}
//provide the mutators
Foo& i(int in_i) { i_ = in_i; return *this; }
Foo& flag(int in_flag) { flag_ = in_flag; return *this; }
void operator() { foo( arg.i_, arg.flag_ ); } //Just forward to the full argument version
protected:
int i_;
bool flag_;
};
Now you can use it like this:
Foo()(); // First () creates temporary, second calls its operator()
Foo().i(20)();
Foo().flag(false)();
Foo().i(10).flag(false)();
There's some variants on this trick that you can use. You can put the arguments into a struct with mutators, but write a void foo(FooArgs) function. In this case you end up with something like:
foo( FooArgs().i(10) );
You can also call foo from from the Foo destructor rather than operator(). In that case your calls look like this:
Foo().i(20); // foo called when this temporary destructs
Let me say we have a simple programming task. But for the sake of clarity I start with few code samples.
First of all we written a some kind of data container class but for the purposes of task no matter what the class is. We just need it to behave const-correct.
class DataComponent {
public:
const std::string& getCaption() const {
return caption;
}
void setCaption(const std::string& s) {
caption = s;
}
private:
std::string caption;
};
Then let us assume we've got a generic class that behaves like facade over arbitrary incapsulated class instance. Say we overloaded member access operator (->).
template <typename T> class Component {
public:
Component() { instance = new T(); }
...
const T* operator-> () const {
return instance;
}
T* operator-> () {
// but there might be additional magic
return instance;
}
private:
T *instance;
};
At this point I should say how I want this to work:
if we're calling non-const member functions of underlying class through member access operator (component->setCaption("foo")) compilier treats non-const T* operator-> () as the best choice.
otherwise if we are trying to call const member functions of underlying class same way (component->getCaption()) compiliers selects const T* operator-> () const on the other hand.
This code sample above won't work this way so I'm curious about possibility to give compiler a behavior like that I have mentioned. Any propositions.
EDIT: Let our member access operator overloaded this way:
const T* operator-> () const { return instance; }
T* operator-> () {
cout << "something going change" << endl;
return instance;
}
And let us have a variable Component<DataComponent> c somewhere. Then on the call to c->getCaption() stdout should remain silent but on the call to c->setCaption("foo") stdout should warn us that something is going to change. VS 2010 compilier makes stdout warn us on each of these calls.
I understand that such semantics suppose that c behaves as const and non-const at the same time. But curiousity is still in my mind.
Whether a const or non-const member is invoked is determined purely by the constness of the object on which it is invoked, not by some subsequent operation. That determination is made before any consideration of the particular method you're invoking in DataComponent. You could still hack up the required functionality less directly using proxy object around DataComponent, with both const and non-const forwarding getCaption()s.
EDIT: details as requested (off the top of my head). You'll need to forward declare some of this stuff - I didn't bother as it makes it even more confusing. Do chip in with any concerns / feedback. Note that this basically assumes you can't / don't want to modify Component for some reason, but it's not a generic templated solution that can simply be wrapped around any arbitrary type - it's very heavily coupled and has a high maintenance burden.
// know they can't call a non-const operation on T, so this is ok...
const T* Component::operator->() const { return instance; }
// they might invoke a non-const operation on T, so...
DataComponent::Proxy Component::operator->() { return DataComponent.getProxy(*this); }
in class DataComponent:
struct Proxy
{
Component& c_;
DataComponent& d_;
Proxy(Component& c, DataComponent& d) : c_(c), d_(d) { }
const std::string& get_caption() const { return d_.get_caption(); }
void set_caption(const std::string& s)
{
c_.on_pre_mutator(d_);
d_.set_caption(s);
c_.on_post_mutator(d_);
}
};
then
DataComponent::Proxy DataComponent::getProxy(Component& c) { return Proxy(c, *this); }
So, this means somewhere you have to hand-code forwarding functions. It's a pain, but if you're doing this for debugging or testing it's not unreasonable. If you're doing this so you can add a lock or something, then there are probably better alternatives.