I really like the idea of properties in C#, and as a little side project, I've been tinkering with the idea of implementing them in C++. I ran into this example https://stackoverflow.com/a/5924594/245869 which seems fairly nice, but I couldn't help but think that lambdas and non-static data member initialization may make it possible to use some very nice syntax with this idea. Here's my implementation:
#include <iostream>
#include <functional>
using namespace std;
template< typename T >
class property {
public:
property(function<const T&(void)> getter, function<void(const T&)> setter)
: getter_(getter),
setter_(setter)
{};
operator const T&() {
return getter_();
};
property<T>& operator=(const T& value) {
setter_(value);
}
private:
function<const T&(void)> getter_;
function<void(const T&)> setter_;
};
class Foobar {
public:
property<int> num {
[&]() { return num_; },
[&](const int& value) { num_ = value; }
};
private:
int num_;
};
int main() {
// This version works fine...
int myNum;
property<int> num = property<int>(
[&]() { return myNum; },
[&](const int& value) { myNum = value; }
);
num = 5;
cout << num << endl; // Outputs 5
cout << myNum << endl; // Outputs 5 again.
// This is what I would like to see work, if the property
// member of Foobar would compile...
// Foobar foo;
// foo.num = 5;
// cout << foo.num << endl;
return 0;
}
I can use my property class normally [see the example in main()], but MinGW with g++4.7 doesn't particularly care for my attempt at using the property as a data member:
\property.cpp: In lambda function:
\property.cpp:40:7: error: invalid use of non-static data member 'Foobar::num_'
So it seems the concept of my property implementation works, but it might be in vain because I can't access other data members from my lambda functions. I'm not sure how the standard defines what I'm trying to do here, am I completely out of luck, or am I just not doing something right here?
Your property is a different object (instance of property<int>) from the containing object (instance of Foobar). As such, its member functions get passed a different this, not the one you'd need to access num_ -- so you can't do it that way. If the lambdas were defined in a non-static member function of Foobar, they would have captured that function's this argument and would have had access to the enclosing object's members (explicitly, as this->num_). But the lambdas are defined in the class, where the non-static data members don't actually exist. If the lambdas did have access to num_, which num_, of which instance of Foobar, would have been that?
The easiest solution that I see is for the property to store a pointer to the enclosing object. That way, it can freely access its non-static members. The downside is that the declaration is slightly more complex (you'd have to do property<int, Foobar> num) and you'd need to initialize the property by passing the this pointer. So you won't be able to do it in the class, it would have to be in the constructor's initialization list, hence negating the advantage of C++11's data member initialization.
At that point, this would be available to the lambdas to capture anyway (by value, not by reference!) so your code would actually work with minimal changes, if you moved the initialization of the property to Foobar's constructor(s):
Foobar::Foobar():
num {
[this]() { return this->num_; },
[this](const int& value) { this->num_ = value; }
}
{
}
Does anyone know whether this, as passed to whatever constructor happens to be invoked, is available for non-static member initialization in the class definition? I suspect it isn't, but if it were, the same construction would work inside the class definition.
Related
In summary, I have a class inherited from std::enabled_shared_from_this, and there is a factory method return an std::unique_ptr of it. In another class, I convert the std::unique_ptr of the previous class object to std::shared_ptr, and then I call shared_from_this(), which then throws std::bad_weak_ptr. The code is shown below:
#include <memory>
#include <iostream>
struct Executor;
struct Executor1 {
Executor1(const std::shared_ptr<Executor>& executor,
int x): parent(executor) {
std::cout << x << std::endl;
}
std::shared_ptr<Executor> parent;
};
struct Backend {
virtual ~Backend() {}
virtual void run() = 0;
};
struct Executor: public Backend, public std::enable_shared_from_this<Executor> {
const int data = 10;
virtual void run() override {
Executor1 x(shared_from_this(), data);
}
};
// std::shared_ptr<Backend> createBackend() {
std::unique_ptr<Backend> createBackend() {
return std::make_unique<Executor>();
}
class MainInstance {
private:
std::shared_ptr<Backend> backend;
public:
MainInstance(): backend(createBackend()) {
backend->run();
}
};
int main() {
MainInstance m;
return 0;
}
Indeed changing std::unique_ptr<Backend> createBackend() to std::shared_ptr<Backend> createBackend() can solve the problem, but as I understand, in general, the factory pattern should prefer return a unique_ptr. Considering a good pratice of software engineering, is there a better solution?
[util.smartptr.shared.const]/1 In the constructor definitions below, enables shared_from_this with p, for a pointer p of type Y*, means that if Y has an unambiguous and accessible base class that is a specialization of enable_shared_from_this (23.11.2.5), then [magic happens that makes shared_from_this() work for *p - IT]
template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
[util.smartptr.shared.const]/29 Effects: ... equivalent to shared_ptr(r.release(), r.get_deleter())...
template<class Y, class D> shared_ptr(Y* p, D d);
[util.smartptr.shared.const]/10 Effects: ... enable shared_from_this with p
Your example executes std::shared_ptr<Backend>(uptr) where uptr is std::unique_ptr<Backend>, which is equivalent to std::shared_ptr<Backend>(p, d) where p is of type Backend*. This constructor enables shared_from_this with p - but that's a no-op, as Backend doesn't have an unambiguous and accessible base class that is a specialization of enable_shared_from_this
In order for Executor::enable_from_this to work, you need to pass to a shared_ptr constructor a pointer whose static type is Executor* (or some type derived therefrom).
Ok, I find a simple solution, that is, using auto as the return type of the factory function, instead of std::unique_ptr or std::shared_ptr, and keeping std::make_unique inside the factory function. The factory function createBackend should be:
auto createBackend() {
return std::make_unique<Executor>();
}
In this case, the return type can be automatically determined, although I don't know how it works exactly. This code can return either unique_ptr or shared_ptr, which should be better than just using shared_ptr. I tested clang and gcc, and both of them worked, but I am still not sure if this is gauranteed by the type deduction and the implicit conversion.
Update:
Actually, I have found that auto deduces the return type above as std::unique_ptr<Executor> instead of std::unique_ptr<Backend>, which might be the reason why the code works. But using auto has an issue: if you return the smart pointer in an if-else block, where the return type varies depending on some parameters, then auto cannot determine the type. For example:
std::unique_ptr<Backend> createBackend(int k = 0) {
if (k == 0) {
return std::make_unique<Executor>();
}
else {
return std::make_unique<Intepreter>();
}
}
Here, both Executor and Intepreter derive from Backend. I think a correct solution includes:
Inherit Backend instead of its derived classes from std::enable_shared_from_this;
Use dynamic_pointer_cast<Derived class> to cast the shared_ptr to derived class after shared_from_this.
The full code is listed in:
https://gist.github.com/HanatoK/8d91a8ed71271e526d9becac0b20f758
I want to write a class that makes use of numerical quadrature. The quadrature order defines the size of some containers that I will use. I would like to make a type alias for such containers and it has to depend on the quadrature order.
The following code shows my trials. It feels suboptimal in the sense that I have to repeat the order in the type alias definition:
#include <array>
class Quadrature
{
public:
static constexpr unsigned int getOrder()
{
return 3;
}
// This line doesn't compile!
//
// using WeightsContainer = std::array<double, getOrder()>;
//
// g++ says "error: 'static constexpr unsigned int Quadrature::getOrder()'
// called in a constant expression before its definition is complete"
// This line compiles, but repeats the order. :-(
using WeightsContainer = std::array<double, 3>;
private:
WeightsContainer container;
};
One solution that I have found is introducing a template parameter Order. But actually I wanted to determine the quadrature order and introducing the template parameter would make it variable.
Is there a possibility to make the order a compile-time constant and use it within my type alias definition?
Edit:
For completeness, I could of course use a preprocessor define. But that feels old-fashioned. :-)
Edit 2:
Okay, I have found another possibility. I could add a function outside the class scope like this:
constexpr unsigned int order()
{
return 3;
}
But that feels wrong, because this is a property of the class and therefore should be within class scope!
One thing you can do is to move the value into a member variable:
class Quadrature
{
private:
static constexpr unsigned int _order = 3;
public:
static constexpr unsigned int getOrder()
{
return _order;
}
using WeightsContainer = std::array<double, _order>;
// ...
};
If you need more complicated computations instead of just return 3, under C++17 you can use a lambda as #Quentin mentioned:
class Quadrature
{
public:
static constexpr auto getOrder = []()
{
return ...;
};
using WeightsContainer = std::array<double, getOrder()>;
// ...
};
Otherwise, you will need to pull the function outside of class scope for reasons mentioned here.
#include <iostream>
#include <memory>
using namespace std;
class Demo {
static shared_ptr<Demo> d;
Demo(){}
public:
static shared_ptr<Demo> getInstance(){
if(!d)
d.reset(new Demo);
return d;
}
~Demo(){
cout << "Object Destroyed " << endl;
}
};
// shared_ptr<Demo> Demo::d(new Demo); // private ctor is accepted
shared_ptr<Demo> Demo::d;
int main()
{
shared_ptr<Demo> d(Demo::getInstance());
cout << d.use_count() << endl;
return 0;
}
is this the correct way to implement the singleton class using shared_ptr
please see above commented line to initialize the static shared_ptr how come we can create an object here to initialize shared_ptr with a private construct
This is not thread-safe: two threads calling getInstance would cause a data race. A common approach is to use a function-scope static variable:
static shared_ptr<Demo> getInstance(){
static shared_ptr<Demo> d(new Demo);
return d;
}
Such a variable is guaranteed to be initialized exactly once, when control passes over its definition for the first time, and in a thread-safe manner.
At this point though, it's not at all clear why you would want to use shared_ptr. You could just as well do
static Demo& getInstance(){
static Demo d;
return d;
}
This is a textbook implementation of a singleton (well, one of).
Re: initialize with a private constructor. I'm not sure I understand the nature of your confusion. Are you asking why Demo::getInstance can use private constructor of Demo? Well, because it's a member of Demo, and members of a class can access private members of that class. Are you asking why Demo::getInstance can call shared_ptr<Demo>::reset() passing a Demo* pointer? Well, because reset() is a public member function of shared_ptr, taking a pointer as a parameter. Which part of this process do you find controversial?
My 2nd Question above is that how come private constructor called out side of class while instantiating the static member
// shared_ptr<Demo> Demo::d(new Demo); // private ctor is accepted
I think return local static wont work , see below example object destroyed twice
#include <iostream>
using namespace std;
class Demo {
public:
static Demo & getInstance(){
static Demo d;
return d;
}
~Demo(){
cout << "Demo destroyed" << endl;
}
};
void fun(){
Demo l = Demo::getInstance();
}
int main()
{
fun();
cout << "Hello World" << endl;
}
Some comments from 1 to help with the discussion. Static variable will be destroyed uppon exit of the application, so we don't need to use the smart pointer at this stage as mentioned above.
"If multiple threads attempt to initialize the same static local variable concurrently, the initialization occurs exactly once (similar behavior can be obtained for arbitrary functions with std::call_once).
Note: usual implementations of this feature use variants of the double-checked locking pattern, which reduces runtime overhead for already-initialized local statics to a single non-atomic boolean comparison.
(since C++11)
The destructor for a block-scope static variable is called at program exit, but only if the initialization took place successfully. "
Update: I'm looking to see if there's a way to zero-initialize the entire class at once, because technically, one can forget adding a '= 0' or '{}' after each member. One of the comments mentions that an explicitly defaulted no-arg c-tor will enable zero-initialization during value-initialization of the form MyClass c{};. Looking at http://en.cppreference.com/w/cpp/language/value_initialization I'm having trouble figuring out which of the statements specify this.
Initialization is a complex topic now since C++11 has changed meaning and syntax of various initialization constructs. I was unable to gather good enough info on it from other questions. But see, for example, Writing a Default Constructor Forces Zero-Initialization?.
The concrete problem I'm facing is: I want to make sure members of my classes are zeroed out both for (1) classes which declare a default c-tor, and for (2) those which don't.
For (2), initializing with {} does the job because it's the syntax for value-initialization, which translates to zero-initialization, or to aggregate initialization if your class is an aggregate - case in which members for which no initializer was provided (all!) are zero-initialized.
But for (1) I'm still not sure what would be the best approach. From all info I gather I learned that if you provide a default c-tor (e.g. for setting some of the members to some values), you must explicitly zero remaining members, otherwise the syntax MyClass c = MyClass(); or the C++11 MyClass c{}; will not do the job. In other words, value-initialization in this case means just calling your c-tor, and that's it (no zero-ing).
You run into the same situation if you declare a c-tor that takes values, and sets those values to a subset of the members, but you'd like other members to be zero-ed: there is no shorthand for doing it - I'm thinking about 3 options:
class MyClass
{
int a;
int b;
int c;
MyClass(int a)
{
this->a = a;
// now b and c have indeterminate values, what to do? (before setting 'a')
// option #1
*this = MyClass{}; // we lost the ability to do this since it requires default c-tor which is inhibited by declaring this c-tor; even if we declare one (private), it needs to explicitly zero members one-by-one
// option #2
std::memset(this, 0, sizeof(*this)); // ugly C call, only works for PODs (which require, among other things, a default c-tor defaulted on first declaration)
// option #3
// don't declare this c-tor, but instead use the "named constructor idiom"/factory below
}
static MyClass create(int a)
{
MyClass obj{}; // will zero-initialize since there are no c-tors
obj.a = a;
return obj;
}
};
Is my reasoning correct?
Which of the 3 options would you choose?
What about using in-class initialization?
class Foo
{
int _a{}; // zero-it
int _b{}; // zero-it
public:
Foo(int a): _a(a){} // over-rules the default in-class initialization
};
Option 4 and 5:
option 4:
MyClass(int a) :a(a), b(0), c(0)
{
}
option 5:
class MyClass
{
int a = 0;
int b = 0;
int c = 0;
MyClass(int a) : a(a) {
}
}
In my humble opinion, the simplest way to ensure zero-initialization is to add a layer of abstraction:
class MyClass
{
struct
{
int a;
int b;
int c;
} data{};
public:
MyClass(int a) : data{a} {}
};
Moving the data members into a struct lets us use value-initialization to perform zero-initialization. Of course, it is now a bit more cumbersome to access those data members: data.a instead of just a within MyClass.
A default constructor for MyClass will perform zero-initialization of data and all its members because of the braced-initializer for data. Additionally, we can use aggregate-initialization in the constructors of MyClass, which also value-initializes those data members which are not explicitly initialized.
The downside of the indirect access of the data members can be overcome by using inheritance instead of aggregation:
struct my_data
{
int a;
int b;
int c;
};
class MyClass : private my_data
{
MyClass() : my_data() {}
public:
MyClass(int a) : MyClass() { this->a = a; }
};
By explicitly specifying the base-initializer my_data(), value-initialization is invoked as well, leading to zero-initialization. This default constructor should probably be marked as constexpr and noexcept. Note that it is no longer trivial. We can use initialization instead of assignment by using aggregate-initialization or forwarding constructors:
class MyClass : private my_data
{
public:
MyClass(int a) : my_data{a} {}
};
You can also write a wrapper template that ensures zero-initialization, thought the benefit is disputable in this case:
template<typename T>
struct zero_init_helper : public T
{
zero_init_helper() : T() {}
};
struct my_data
{
int a;
int b;
int c;
};
class MyClass : private zero_init_helper<my_data>
{
public:
MyClass(int a) { this->a = a; }
};
Having a user-provided constructor, zero_init_helper no longer is an aggregate, hence we cannot use aggregate-initialization any more. To use initialization instead of assignment in the ctor of MyClass, we have to add a forwarding constructor:
template<typename T>
struct zero_init_helper : public T
{
zero_init_helper() : T() {}
template<typename... Args>
zero_init_helper(Args&&... args) : T{std::forward<Args>(args)...} {}
};
class MyClass : private zero_init_helper<my_data>
{
public:
MyClass(int a) : zero_init_helper(a) {}
};
Constraining the constructor template requires some is_brace_constructible trait, which is not part of the current C++ Standard. But this already is a ridiculously complicated solution to the problem.
It is also possible to implement your option #1 as follows:
class MyClass
{
int a;
int b;
int c;
MyClass() = default; // or public, if you like
public:
MyClass(int a)
{
*this = MyClass{}; // the explicitly defaulted default ctor
// makes value-init use zero-init
this->a = a;
}
};
What about constructor delegation?
class MyClass
{
int a;
int b;
int c;
MyClass() = default; // or public, if you like
public:
MyClass(int a) : MyClass() // ctor delegation
{
this->a = a;
}
};
[class.base.init]/7 suggests that the above example shall invoke value-initialization, which leads to zero-initialization since the class does not have any user-provided default constructors [dcl.init]/8.2. Recent versions of clang++ seem to zero-initialize the object, recent versions of g++ do not. I've reported this as g++ bug #65816.
I have a beginner question on the move assigment in c++11. Let say that I have a class A provided with a move assigment operator:
class A
{
public:
A();
~A();
A& operator=(A&&);
...
}
I also have a class B containing a class A object and provided with a move assignment operator
class B
{
public:
B();
~B();
B& operator=(B&&);
...
private:
A Test;
}
What I was thinking is that the B move assignment operator will call the move assignment operator of its member so I tried this method:
B& B::operator=(B&& Other)
{
...
Test = Other.Test;
...
return *this;
}
But this is not working since the move assignment of class A is not called.
Instead I was able to make the program work by using this method:
B& B::operator=(B&& Other)
{
...
Test = std::move(Other.Test);
...
return *this;
}
I do not understand why the first method is not working. I was thinking that since a constructor will call its members constructors the move assignment operator should do the same. Am I wrong or I made a mistake in my code? Can someone explain, thanks!
Other.Test is not an rvalue expression since it has a name. OTOH std::move(Other.Test) has the type A and the value category xvalue (i.e., an rvalue). Thus, it can bind to the move constructor.
(EDIT : Shamelessly copied #dyp's comment. Thanks, #dyp and #KerrekSB.)
#Pradhan is correct - you need to use std::move to move the members in the implementation of the move assignment operator. However, if that is all that is needed to implement your move constructor, then you can declare the operator to use the default implementation:
#include <memory>
class A {
public:
A() : p{} { }
~A() { }
A &operator=(A &&) = default;
// Instead of:
// A &operator=(A &&other) {
// p = std::move(other.p);
// return *this;
// }
private:
std::unique_ptr<int> p;
};
int main() {
A a;
A b;
b = std::move(a);
return 0;
}