How do I create a reference to immutable classes, but while keeping the ability to reassign the reference, sort of like string?
import std.stdio;
immutable class Test {
string test(){
return "test";
}
}
void main(){
auto test = new Test;
writeln(test.test);
}
This causes an error, because the created instance is not immutable:
test.d(14): Error: immutable method test.Test.test is not callable using a mutable object
new immutable doesn't work either, because the resulting variable cannot be assigned a new one afterwards.
immutable(Test)* would work, but is there a way avoiding pointers?
Use std.typecons.Rebindable http://dpldocs.info/experimental-docs/std.typecons.Rebindable.html#examples
import std.typecons;
class Widget { int x; int y() const { return x; } }
auto a = Rebindable!(const Widget)(new Widget);
// Fine
a.y();
// error! can't modify const a
// a.x = 5;
// Fine
a = new Widget;
You can use immutable in the same way of auto to infer types:
immutable test = new Test;
immutable other_test = test;
Related
There is a custom defined map, with an element std::function()>.
The lambda code is working, but I don't know how to expand it to a normal formation. The code is following.
class TestA{
public:
TestA() {}
~TestA() {}
TestA(const TestA &) {}
static void print()
{
cout << __FUNCTION__ << endl;
return;
}
};
void testComplexMap1()
{
typedef map<string, std::function<std::unique_ptr<TestA>()>> TempMap;
TempMap m;
// the lambda format code, it works
//m.insert({ "TestA", []() {return std::unique_ptr<TestA>(new TestA());}});
// I want to expand it, but failed.
TestA *t = new TestA();
//function<unique_ptr<TestA>()> fp(unique_ptr<TestA>(t));
function<unique_ptr<TestA>()> fp(unique_ptr<TestA>(t)()); //warning here
//m.emplace("TestA", fp); // compile error here
}
Any help will be greatly appreciated.
fp is not initialized with a function so compilation fails.
You can expand it like this:
TestA *t = new TestA();
std::unique_ptr<TestA> UT(t);
auto func = [&]() { return move(UT);};
std::function<std::unique_ptr<TestA>()> fp(func);
m.emplace("TestA", fp);
See DEMO.
In C++ everything that looks like it could be a declaration is treated as such.
This means the line
function<unique_ptr<TestA>()> fp(unique_ptr<TestA>(t)());
is interpreted as:
fp is the declaration of a function returning an std::function<unique_ptr<TestA>()> and expecting a parameter called t which is a function pointer to a function returning a std::unique_ptr<TestA> and getting no parameter. (Which is not what you intended.)
This also means that the t in this line is not the same t as in the previous line.
You have to pass fp something that is actually callable like this:
std::unique_ptr<TestA> f() {
return std::make_unique<TestA>();
}
void testComplexMap1() {
// ...
function<unique_ptr<TestA>()> fp(f);
m.emplace("TestA1", fp);
}
If you want to add a function to the map that wraps an existing pointer into a unique_ptr you would need either a functor:
class Functor {
public:
Functor(TestA * a) : m_a(a) {}
~Functor() { delete m_a; }
std::unique_ptr<TestA> operator()(){
auto x = std::unique_ptr<TestA>(m_a);
m_a = nullptr;
return std::move(x);
}
private:
TestA * m_a;
};
void testComplexMap1() {
//...
TestA * t = new TestA();
m.emplace("TestA", Functor(t));
}
Or a lambda with capture:
void testComplexMap1() {
//...
TestA * t = new TestA();
m.emplace("TestA", [t](){ return std::unique_ptr<TestA>(t); });
}
The lamda is translated more or less to something like the Functor class. However in each case you have to be really careful: The functions in the map that encapsulate an existing pointer into a std::unique_ptr can and should only be called once.
If you don't call them, memory allocated for t won't be freed. If you call them more than once you get either a std::unique_ptr to nullptr (in my Functor class variant) or a more than one std::unique_ptr tries to manage the same memory region (in the lambda with capture variant), which will crash as soon as the second std::unique_ptr is deleted.
In short: I would advice against writing code like this and only put functions in the map that are callable multiple times.
I'm currently trying to implement a class around a valarray object and i get a exception when trying to run:
class TestClass
{
public:
valarray<int> va;
TestClass() { va.resize(5, 1); }
slice_array<int>& get_slice()
{
return va[slice(0, 3, 2)];
}
};
//In main():
TestClass obj;
slice_array<int>& ref = obj.va[slice(0,3,2)];
ref = -1; //OK
obj.get_slice() = -1; //Throws exception
Aren't the two assignments the same thing?
I solved it myself:
It seems that a valarray[slice(int, int, int)] is not an lvalue or is temporary, so it's not allowed to initialize a reference with such an object (oddly enough, VS2012 allows to do so in some cases).
I would like to benchmark the performance of using a const cache for some static function inside a cache. So I have something like that:
class Foo {
static double cost(int factor) { <moderately complex function> };
// Other stuff using the cost() function
};
And I would like to benchmark against an alternative version like this one:
class Foo {
private:
static double _cost(int factor) { <same function as before> };
static const double cost_cache[MAX_FACTOR] = ???;
public:
static double cost(int factor) { return cost_cache[factor]; };
// Other stuff
}
With a way to initialize my cost_cache array in a way equivalent to
for (int idx = 0; i < MAX_FACTOR; ++i)
cost_cache[idx] = _cost(idx);
In a high-level functional language I would use a map primitive. How do I properly initialize that in C++11 (or C++14 ?) I saw other posts addressing similar questions, like Initializing private member static const array, but its solution is inapplicable in my case, I can't put the 10k values verbatim in source.
I'm using clang++
What about first initialize the array with "{}",
and then overwrite elements by a method that loads values from a file?
I am writting a little ruby module with some very simple classes in C:
typedef struct window_t {
GtkWidget * widget;
}
static void c_window_struct_free(window_t *c)
{
if(c)
{
ruby_xfree(c);
}
}
static VALUE c_window_struct_alloc( VALUE klass)
{
return Data_Wrap_Struct(klass, NULL, c_window_struct_free,ruby_xmalloc(sizeof(window_t)));
}
VALUE c_window = rb_define_class_under(m_rtortosa, "Window", c_widget)
rb_define_method(c_window, "set_title",RUBY_METHOD_FUNC(window_set_title), 1);
//For each class I don't rewritte any "new" or "initialize" function. I let the default
When my module is initialized, a gtk window is created, and I have a ruby method for this module that call:
static VALUE rtortosa_window(VALUE self)
{
VALUE win;
VALUE m_rtortosa = rb_const_get( rb_cObject, rb_intern( "Rtortosa" ) );
VALUE cWindow = rb_const_get_at( m_rtortosa, rb_intern("Window") );
win = rb_class_new_instance(0, NULL, backbone.rb_objects.cWindow);
window_t *w;
Data_Get_Struct(win,window_t, w);
w->widget = backbone.window.widget;
return win;
}
The problesm occurs when I call the rtortosta_window from ruby, it throws an error like this :
wrong argument type Rtortosa::Window (expected Data) (TypeError)
After investigations this message is comming from the Data_Get_Struct function.
I don't see what I am doing wrong, I have a notebook class that is written in the same way but it works as expected.
I have forgotten to bind the alloc function to the class:
rb_define_alloc_func(c_window, c_window_struct_alloc);
I need helping trying to retrieve data held in a std::list<boost::shared_ptr<boost::any>>
I working on a Singleton Controller class with a private std::list. Client class(es) will be able to add/remove/edit concrete class objects to be used by the program through this Controller class.
The reason for using boost::shared_ptr is because I assign a unique objID to each concrete class created. Once instance objs are added to controller, user will be able to search and remove objs later. The Add(....) and Remove(...) overloaded methods for each concrete class work fine.
I am now trying to create getObject(int index) & setObject(int index) methods but can't seem to figure out how to cast the returned pointer to a Concrete class.
Please advise.
My current code:
//===============================================================
//Singleton.h controller class
private:
static Singleton *mgr;
typedef boost::shared_ptr<boost::any> Shapes_Ptr;
//private static list
static std::list<Shapes_Ptr> shapes;
public:
const Shapes_Ptr getObject( int index) const; //Return Shape
Shapes_Ptr EditObject( const int index ); //Edit Shape
Info(); //Prints contents of instance to console screen
//===============================================================
//Singleton.cpp
//Return Shape
const Shapes_Ptr getObject( int index) const
{
int cc = 0;
if ( (int)shapes.size() > ZERO && index < (int)shapes.size() )
{
list<Shapes_Ptr>::const_iterator i;
for ( i = shapes.begin(); i != shapes.end(); ++i )
{
if ( cc == index )
{
return (*i);
break;
}
else { ++cc; }
}//for-loop
}
}
//Edit Shape
Shapes_Ptr EditObject( const int index )
{
//same code as getObject()...
}
//===============================================================
//main.cpp
Singleton *contrl= Singleton::Instance();
int main()
{
for ( int i=0; i< 2; ++i )
{
contrl->CreateObject(Box2D() );
}
for ( int i = contrl->Begin(); i< contrl->End(); ++i )
{
if ( boost::any_cast<boost::any> (contrl->getObject(i)).type() == typeid(Physics::Box2D) )
{
//Code compiles but crashes on launch....
any_cast<Box2D> (contrl->getObject(i) ).Info(); // <== ERROR CODE
}
//More if checks for other Concrete classes....
}
}
Putting aside whatever the particular issue with your current code is, I think there is an issue with your design.
You have this Singleton manager class that acts as a sort of pool and also as you say assigns unique IDs to each object so they can be found later. But you know what lets code find objects? Pointers! If you use a normal pool, one per type hierarchy (so no more Boost Any), you may find it just as useful, and there will be less nasty if/else typeid-checking code (which everyone would agree is not a good use of RTTI, aside from being poor OOP).
So, what do you say? Chuck this, and use Boost Pool if you want something to allocate your objects from a central place, and use pointers as your unique IDs, thus avoiding lookups along the way.