I want to write an class that optimizes a parameter. I thought the following interface would be desirable:
class Optimization {
public:
std::shared_ptr<Part> getParameter() const {
return m_parameter;
}
void setParameter(const std::shared_ptr<Parameter>& parameter) {
m_parameter = parameter;
}
private:
std::shared_ptr<Paramter> m_parameter;
};
Now sometimes I may not be interested in the starting value of the parameter so I would like to call setParameter like this:
setParameter(std::make_shared(Parameter(...)));
(now I guess it makes more sense why there is a getter function)
So as I understand it the setParameter function is not taking advantage that I am passing an rvalue to setParameter.
So my question is how can I solve this?
Should I add another function
void setParameter(std::shared_ptr<Parameter>&& parameter) {
m_parameter = std::move(parameter);
}
Does this avoid unneccessary copies?
Or would a universal reference, maybe like this:
template<typename T>
void setParameter(T&& parameter) {
m_parameter = std::forward<T>(parameter);
}
be a better solution?
The right implementation is like below
void setParameter(std::shared_ptr<Parameter> parameter) {
m_parameter = std::move(parameter);
}
rvalue will be moved to parameter and parameter will be moved to m_parameter. Two moves, like you want.
lvalue will be copied to parameter and parameter will be moved to m_parameter. One copy and one move, the similar like with const reference, plus cheap moving that will be optimized.
You can read about this in the book "Effective C++" of Scott Meyers.
std::piecewise_construct is a constexpr flag which can be used to indicate piecewise construction of a data object.
Explanatory comments inline
#include <memory>
#include <utility>
struct Parameter
{
// some constructor
Parameter(int, int);
};
class Optimization {
public:
std::shared_ptr<Parameter> getParameter() const {
return m_parameter;
}
// original overload
void setParameter(const std::shared_ptr<Parameter>& parameter) {
m_parameter = parameter;
}
// rvalue overload
void setParameter(std::shared_ptr<Parameter>&& parameter) {
m_parameter = std::move(parameter);
}
// piecewise overload which forwards arguments
template<typename...Args>
void setParameter(std::piecewise_construct_t, Args&&...args)
{
m_parameter = std::make_shared<Parameter>(std::forward<Args>(args)...);
}
private:
std::shared_ptr<Parameter> m_parameter;
};
int main()
{
auto o = Optimization();
// original
o.setParameter(std::make_shared<Parameter>(1,2));
// equivalent to...
o.setParameter(std::piecewise_construct, 1, 2);
}
Related
I read few questions here on SO about this topic which seems yet confusing to me. I've just begun to learn C++ and I haven't studied templates yet or operator overloading and such.
Now is there a simple way to overload
class My {
public:
int get(int);
char get(int);
}
without templates or strange behavior? or should I just
class My {
public:
int get_int(int);
char get_char(int);
}
?
No there isn't. You can't overload methods based on return type.
Overload resolution takes into account the function signature. A function signature is made up of:
function name
cv-qualifiers
parameter types
And here's the quote:
1.3.11 signature
the information about a function that participates in overload
resolution (13.3): its parameter-type-list (8.3.5) and, if the
function is a class member, the cv-qualifiers (if any) on the function
itself and the class in which the member function is declared. [...]
Options:
1) change the method name:
class My {
public:
int getInt(int);
char getChar(int);
};
2) out parameter:
class My {
public:
void get(int, int&);
void get(int, char&);
}
3) templates... overkill in this case.
It's possible, but I'm not sure that it's a technique I'd recommend for
beginners. As in other cases, when you want the choice of functions to
depend on how the return value is used, you use a proxy; first define
functions like getChar and getInt, then a generic get() which
returns a Proxy like this:
class Proxy
{
My const* myOwner;
public:
Proxy( My const* owner ) : myOwner( owner ) {}
operator int() const
{
return myOwner->getInt();
}
operator char() const
{
return myOwner->getChar();
}
};
Extend it to as many types as you need.
As stated before, templates are overkill in this case, but it is still an option worth mentioning.
class My {
public:
template<typename T> T get(int);
};
template<> int My::get<int>(int);
template<> char My::get<char>(int);
No, you can't overload by return type; only by parameter types, and const/volatile qualifiers.
One alternative would be to "return" using a reference argument:
void get(int, int&);
void get(int, char&);
although I would probably either use a template, or differently-named functions like your second example.
Resurrecting an old thread, but I can see that nobody mentioned overloading by ref-qualifiers. Ref-qualifiers are a language feature added in C++11 and I only recently stumbled upon it - it's not so widespread as e.g. cv-qualifiers. The main idea is to distinguish between the two cases: when the member function is called on an rvalue object, and when is called on an lvalue object. You can basically write something like this (I am slightly modifying OP's code):
#include <stdio.h>
class My {
public:
int get(int) & { // notice &
printf("returning int..\n");
return 42;
}
char get(int) && { // notice &&
printf("returning char..\n");
return 'x';
};
};
int main() {
My oh_my;
oh_my.get(13); // 'oh_my' is an lvalue
My().get(13); // 'My()' is a temporary, i.e. an rvalue
}
This code will produce the following output:
returning int..
returning char..
Of course, as is the case with cv-qualifiers, both function could have returned the same type and overloading would still be successful.
You can think this way:
You have:
int get(int);
char get(int);
And, it is not mandatory to collect the return value of the function while invoking.
Now, You invoke
get(10); -> there is an ambiguity here which function to invoke.
So, No meaning if overloading is allowed based on the return type.
While most of the other comments on this problem are technically correct, you can effectively overload the return value if you combine it with overloading input parameter. For example:
class My {
public:
int get(int);
char get(unsigned int);
};
DEMO:
#include <stdio.h>
class My {
public:
int get( int x) { return 'I'; };
char get(unsinged int x) { return 'C'; };
};
int main() {
int i;
My test;
printf( "%c\n", test.get( i) );
printf( "%c\n", test.get((unsigned int) i) );
}
The resulting out of this is:
I
C
There is no way to overload by return type in C++. Without using templates, using get_int and get_char will be the best you can do.
You can't overload methods based on return types. Your best bet is to create two functions with slightly different syntax, such as in your second code snippet.
you can't overload a function based on the return type of the function.
you can overlead based on the type and number of arguments that this function takes.
I used James Kanze's answer using a proxy:
https://stackoverflow.com/a/9569120/262458
I wanted to avoid using lots of ugly static_casts on a void*, so I did this:
#include <SDL_joystick.h>
#include <SDL_gamecontroller.h>
struct JoyDev {
private:
union {
SDL_GameController* dev_gc = nullptr;
SDL_Joystick* dev_js;
};
public:
operator SDL_GameController*&() { return dev_gc; }
operator SDL_Joystick*&() { return dev_js; }
SDL_GameController*& operator=(SDL_GameController* p) { dev_gc = p; return dev_gc; }
SDL_Joystick*& operator=(SDL_Joystick* p) { dev_js = p; return dev_js; }
};
struct JoyState {
public:
JoyDev dev;
};
int main(int argc, char** argv)
{
JoyState js;
js.dev = SDL_JoystickOpen(0);
js.dev = SDL_GameControllerOpen(0);
SDL_GameControllerRumble(js.dev, 0xFFFF, 0xFFFF, 300);
return 0;
}
Works perfectly!
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
after yesterday's rip-roaring thread at How to implement a simple event queue? , I decided to finally make the big leap to c++11. Just before c++14 comes out probably...
Anyway, it occured to me that variadic functions are the perfect way forward in this enjoyable endeavour. They probably aren't really, but anyway, I managed to steal and bastardize some code I found somewhere, and ended up with this:
#include <iostream>
#include <functional>
#include <queue>
class Event
{
public:
int timeOfCompletion;
std::function<void()> function;
inline bool operator<(const Event& target) const
{
return target.timeOfCompletion < timeOfCompletion;
}
};
class System
{
public:
int someValue;
std::priority_queue<Event> funcs;
System()
{
someValue = 100;
}
template<typename Func, typename...Args>
void addFunctionToQueue(const int t , const Func&& myFunc, Args&&... myArgs)
{
Event newEvent;
std::function<void()> func = std::bind( std::forward<Func>(myFunc), std::ref(myArgs)...);
newEvent.function = func;
newEvent.timeOfCompletion = t;
funcs.push(newEvent);
}
void runAllFunctions()
{
while(!funcs.empty())
{
Event func = funcs.top();
funcs.pop();
func.function();
}
}
static void doStaticFunction(int a)
{
std::cout <<"I would like to change someValue here, but can't :-(\n";
//someValue -= a;//invalid
}
void doNonStaticFunction(int a)
{
someValue -= a;
std::cout <<"Set someValue to " << someValue << "\n";
}
};
int main()
{
System newSystem;
newSystem.doNonStaticFunction(5);
newSystem.addFunctionToQueue(5, System::doStaticFunction, 1);
newSystem.runAllFunctions();
//newSystem.addFunctionToQueue(5, newSystem.doStaticFunction, 1);// is invalid
//newSystem.addFunctionToQueue(5, System::doNonStaticFunction, 1);// is invalid
//newSystem.addFunctionToQueue(5, newSystem.doNonStaticFunction, 1);// is invalid
std::cin.ignore();
return 0;
}
Anyhow, how can I get the "addFunctionToQueue" function to work with non-static functions? I thought I had more questions, but I think if I can get that one answered, my other problems will hopefully be solved...
Remove a const qualifier from the Func parameter.
template<typename Func, typename...Args>
void addFunctionToQueue(int t , Func&& myFunc, Args&&... myArgs)
// ~~~^ no const
Rationale: When using a forwarding reference (or an lvalue reference) type with a template argument deduction, a const qualifier is automatically deduced (depending on the argument's qualifiers). Giving it explicitly prevents the compiler from adding it to the Func type itself, which results in an error when you try to std::forward<Func>. That said, you would need to write std::forward<const Func> instead to avoid the compiler error, but still, that would make no sense, as const T&& is not a forwarding reference.
Non-static member functions require an object for which they will be called, just like you write a.foo(), not foo().
newSystem.addFunctionToQueue(5, &System::doNonStaticFunction, &newSystem, 1);
// ~~~~~~~~~^ context
I have a class template S<T> and because the template parameter is sometimes hard write explicitly I also have a little helper function makeS(...) to deduce the template parameter.
Now the problem is that the constructor of S has a "side effect": it adds itself to a map which then will later be used to iterate over all instances of S. But this effectively makes S<T> s{...}; very different from auto s = makeS(...); (if RVO is not used).
Here is some code which hopefully shows what I'm trying to do. (Note: in the actual program, S has more than a single template parameter and all will be deduced in makeS)
#include <cassert>
#include <iostream>
#include <map>
#include <string>
#include <utility>
using namespace std;
struct Base
{
virtual ~Base() {}
virtual void f() const = 0;
};
static map<string, Base*> Map;
template <typename T>
struct S : Base
{
T Func;
Base* This;
S(string const& name, T func) : Func(std::move(func)), This(this)
{
//
// Automatically add this struct to Map...
//
Map.insert({name, this});
}
virtual void f() const override { Func(); }
};
template <typename T>
S<T> makeS(std::string const& name, T func)
{
return S<T>(name, std::move(func));
}
void func1()
{
std::cout << "func1\n";
}
int main()
{
struct Func2
{
void operator ()() const {
std::cout << "func2\n";
}
};
//
// This is not possible:
//
// S< ??? > s("s", [](){});
//
// This would be ok:
//
// auto F = [](){};
// S<decltype(F)> s("s", F);
//
auto s1 = makeS("s1", func1);
auto s2 = makeS("s2", Func2());
auto s3 = makeS("s3", [](){ std::cout << "func3\n"; });
//
// Manually adding s1,... to the Map is ok, but that's what
// I want to avoid...
//
// Map.insert({"s1", &s1});
// ...
//
assert(&s1 == s1.This);
assert(&s2 == s2.This);
assert(&s3 == s3.This);
for (auto&& I : Map)
{
I.second->f();
}
}
As I understand it, the map will only contain valid pointers if RVO is used in auto s1 = makeS(...) etc. and this is not guaranteed.
Is there a way to deduce the template parameters while at the same time avoiding the need to manually register s1,...?
Your basic problem is you failed to implement the rule of 3. If your destructor needs non-trivial behavior (and if you register yourself in the constructor, this is the case), you must either implement or block assignment and copy construct (and/or move-assign and move-construct).
In this case, we can implement a move-construct and block move-assign, and copy construct and copy assign are implicitly blocked.
First, add name to S. Then implement a move constructor.
template <typename T>
struct S : Base
{
std::string Name;
T Func;
Base* This; // ?? why ?? this looks both dangerous and useless at the same time!
S( S&& s ): Name(std::move(s.Name)), Func(std::move(s.Func)), This(this) {
s.clear(); // technically `move` need not clear.
map[Name] = this; // overwrite
}
S& operator=(S&& s) = delete; // or implement it
now your object is moveable, and when moved it updates the Map. ~S should, I assume, unregister from Map -- detect if your name is empty (and assert at construction you gain a non-empty name), and if it is don't unregister (as you where already moved from).
Now move-construct and elided-construct have the same semantics. RVO failure results in some inefficiency, but no logical failure. Plus, your type is now moveable, which tends to be really useful.
If you need to maintain object identity, use can use std::unique_ptr:
template <typename T>
std::unique_ptr<S<T>> makeS(std::string const& name, T func)
{
return { new S<T>(name, std::move(func)) };
}
Now moving the pointer from place to place won't move the object; the pointer kept in the map will stay valid.
My suggestions to improve your code:
1) Get rid of the side effect in the constructor. Create objects in a factory method only (makeS in your code; you can make it a static member function of S) and register the S objects in that method. To disable object creation in different ways make constructor(s) private.
2) Disable S objects copying/moving and handle the objects for example as shared_ptr/unique_ptr<S> only. When you disable copying/moving you avoid the problem when your map contains a pointer to invalid objects and now you don't need to rely on RVO.
3) Use std::function<void()> instead of T Func;. In that case your class don't need to be a template class (or it will have less template arguments). That will simplify your code.
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