const list, non-const element access - boost

I've a problem with boost intrusive containers.
One of my classes has an intrusive list of some objects, whose lifetimes are strictly managed by it. The objects themselves are meant to be modified by the users of the class, but they are not supposed to modify the list itself. That's why I'm only providing access to the list through a "getList" function, which returns a const version of the intrusive list.
The problem with const intrusive lists is that the elements also turn out to be const when you're trying to iterate through them. But the users should be able to iterate through and modify the items.
I don't want to keep a separate list of pointers to give to the users, because that would invalidate one of the biggest advantages of using intrusive containers. Namely, the ability to remove items from the container in constant time, while the only thing you have is a pointer to the item.
It would be sad to have to give a non-const version of my list just because of a limitation of C++. So the question is: Is there a special const version of the boost intrusive containers, which magically allows item modifications while disallowing any modifications on the list itself?

You don't need to return a list, give an access to separate items by reference

OK, I've designed a complete solution to the problem. Andy's solution is nice, if you don't need to iterate over the items in an efficient manner. But I wanted something that's semantically equivalent to const std::list. Maybe it's an overkill, but performance wise there's almost no difference after optimizations:
The solution is to privately extend the intrusive list with a class called ConstList, which exposes just enough to let BOOST_FOREACH iterate, but not to make any changes by anyone. I've moved the list hook from the item to a child class, so that an item object cannot be used to change the list either. We're storing the child class with the hook, but our iterators are returning references to the item class. I've coded this solution into two templated classes for easy application to any item class.
I've made a header file with the ConstList class and the HookedItem class, followed by the tests.cpp, used to test and benchmark. You'll see that our ConstList class has equal performance while iterating.
It works quite cleanly, and the user code also stays clean. Then this begs the question: Why isn't this already in boost????!?!?
Feel free to use the following code for any purpose :)
P.S: I've had a moment of revelation while coming up with this solution: "const" is nothing but a syntactic sugar for a special case of what you can already achieve with the right class hierarchy. Is that true, or was I over-generalizing?
------------------ ConstList.h -----------------------
#include <boost/intrusive/list_hook.hpp>
template < typename T>
struct type_wrapper{ typedef T type;};
template<class listType, class owner, class item>
class ConstList: private listType {
friend class type_wrapper<owner>::type;
public:
class iterator {
typename listType::iterator it;
public:
typedef std::forward_iterator_tag iterator_category;
typedef item value_type;
typedef int difference_type;
typedef item* pointer;
typedef item& reference;
template<class T>
iterator(const T it): it(it){}
bool operator==(iterator & otherIt) {return it==otherIt.it;}
iterator & operator++() {
it++;
return *this;
}
item & operator*() {
return *it;
}
};
iterator begin() {
return iterator(listType::begin());
}
iterator end() {
return iterator(listType::end());
}
};
template<class item, class owner, class hooktype>
class HookedItem: public item {
friend class type_wrapper<owner>::type;
public:
hooktype hook_;
typedef boost::intrusive::member_hook<HookedItem, hooktype, &HookedItem::hook_> MemberHookOption;
private:
template<class Arg1, class Arg2>
HookedItem(Arg1 &arg1, Arg2 &arg2): item(arg1, arg2){}
};
------------------ tests.cpp -----------------------
#include<cstdio>
#include<boost/checked_delete.hpp>
#include<ConstList.h>
#include<boost/intrusive/list.hpp>
#include<boost/foreach.hpp>
using namespace boost::intrusive;
class myOwner;
class myItem {
public:
int a,b; //arbitrary members
myItem(int a, int b): a(a), b(b){};
};
typedef HookedItem<myItem,myOwner,list_member_hook<> > myHookedItem;
typedef list<myHookedItem, typename myHookedItem::MemberHookOption> myItemList;
typedef ConstList<myItemList,myOwner,myItem> constItemList;
class myOwner {
public:
constItemList constList;
myItemList & nonConstList;
myOwner(): nonConstList(constList) {}
constItemList & getItems() { return constList;}
myItem * generateItem(int a, int b) {
myHookedItem * newItem = new myHookedItem(a,b);
nonConstList.push_back(*newItem);
return newItem;
}
~myOwner() {nonConstList.clear_and_dispose(boost::checked_delete<myHookedItem>);}
};
int main(int argc, char **argv) {
myOwner owner;
int avoidOptimization=0;
for(int i=0; i<1000000; i++) {
owner.generateItem(i,i);
}
clock_t start = clock();
for(int i=0; i<1000; i++)
BOOST_FOREACH(myItem & item, owner.constList)
avoidOptimization+=item.a;
printf ( "%f\n", ( (double)clock() - start ) / CLOCKS_PER_SEC );
start = clock();
for(int i=0; i<1000; i++)
BOOST_FOREACH(myHookedItem & item, owner.nonConstList)
avoidOptimization+=item.a;
printf ( "%f\n", ( (double)clock() - start ) / CLOCKS_PER_SEC );
printf ("%d",avoidOptimization);
return 0;
}
------------ Console Output -----------------
4.690000
4.700000
1764472320

Related

Using variadic templates and move semantics

I am trying to wrap my head around variadic templates,
move semantics, (maybe perfect forwarding?),
and learn how to pass variable down to different functions.
Lets say, there is a class Foo which holds an array of Elem (templated) class instances.
These array elements regularly gets re-initialized (hence the Elem.init function).
Below I am trying to initialize an Elem with three large strings (or any other large objects which implements move semantics) to exactly the place where they will be stored:
In the Foo's array, at a certain location.
Is that even possible to move them to the Foo's vector location right away?
Or will it be always a "copy semantics" instead of a move.
Overall, I am trying to avoid copying large stack allocated strings around and somehow have them be in the target vector's location.
Not sure what would be the best way to do that.
(All i got is a segmentation fault at the moment)
Thank you for reading!
Code below online: https://onlinegdb.com/HJc7U_jIO
#include <iostream>
#include <vector>
#include <string>
class Elem
{
public:
void init(std::string&& s1, std::string&& s2, std::string&& s3)
{
s1 = std::move(s1);
s2 = std::move(s2);
s3 = std::move(s3);
std::cout << mS1 << mS2 << mS3;
}
private:
std::string mS1;
std::string mS2;
std::string mS3;
};
template <class T>
class Foo
{
public:
template <typename... Args>
void add(Args... args)
{
mElements[mNextFreeIndex].init(args...);
mNextFreeIndex++;
}
private:
std::vector<T> mElements;
int mNextFreeIndex;
};
int main()
{
Foo<Elem> foo;
foo.add(std::move("Apple"), std::move("Pear"), std::move("Carrot")); //passing 3 parameters
return 0;
}
To properly "debug" these issues, you may want to write a class with copy & move constructors, destructor and copy & move assignment operators which declare their being executed. Then you can tell what happens with the values as they get passed around and/or created.
Anyway, you're calling the add() method with three std::string&& arguments. But - inside the function, once they are bound to args..., they are now lvalues! You either need to use std::move() in your add() method:
template <typename... Args>
void add(Args... args)
{
mElements[mNextFreeIndex].init(std::move(args)...);
mNextFreeIndex++;
}
or apply forwarding:
template <typename... Args>
void add(Args&&... args)
{
mElements[mNextFreeIndex].init(std::forward<Args>(args)...);
mNextFreeIndex++;
}
On a mostly unrelated note, I would recommend reading this: "Parameter" vs "Argument" regarding the use of these two terms.

C++ Check if generic object has member function matching signature

first post, so hopefully not violating any etiquette. Feel free to give suggestions for making the question better.
I've seen a few posts similar to this one: Check if a class has a member function of a given signature, but none do quite what I want. Sure it "works with polymorphism" in the sense that it can properly check subclass types for the function that comes from a superclass, but what I'd like to do is check the object itself and not the class. Using some (slightly tweaked) code from that post:
// Somewhere in back-end
#include <type_traits>
template<typename, typename T>
struct HasFunction {
static_assert(integral_constant<T, false>::value,
"Second template parameter needs to be of function type."
);
};
template<typename C, typename Ret, typename... Args>
class HasFunction<C, Ret(Args...)> {
template<typename T>
static constexpr auto check(T*) -> typename is_same<
decltype(declval<T>().myfunc(declval<Args>()...)), Ret>::type;
template<typename>
static constexpr false_type check(...);
typedef decltype(check<C>(0)) type;
public:
static constexpr bool value = type::value;
};
struct W {};
struct X : W { int myfunc(double) { return 42; } };
struct Y : X {};
I'd like to have something like the following:
// somewhere else in back-end. Called by client code and doesn't know
// what it's been passed!
template <class T>
void DoSomething(T& obj) {
if (HasFunction<T, int(double)>::value)
cout << "Found it!" << endl;
// Do something with obj.myfunc
else cout << "Nothin to see here" << endl;
}
int main()
{
Y y;
W* w = &y; // same object
DoSomething(y); // Found it!
DoSomething(*w); // Nothin to see here?
}
The problem is that the same object being viewed polymorphically causes different results (because the deduced type is what is being checked and not the object). So for example, if I was iterating over a collection of W*'s and calling DoSomething I would want it to no-op on W's but it should do something for X's and Y's. Is this achievable? I'm still digging into templates so I'm still not quite sure what's possible but it seems like it isn't. Is there a different way of doing it altogether?
Also, slightly less related to that specific problem: Is there a way to make HasFunction more like an interface so I could arbitrarily check for different functions? i.e. not have ".myfunc" concrete within it? (seems like it's only possible with macros?) e.g.
template<typename T>
struct HasFoo<T> : HasFunction<T, int foo(void)> {};
int main() {
Bar b;
if(HasFoo<b>::value) b.foo();
}
Obviously that's invalid syntax but hopefully it gets the point across.
It's just not possible to perform deep inspection on a base class pointer in order to check for possible member functions on the pointed-to type (for derived types that are not known ahead of time). Even if we get reflection.
The C++ standard provides us no way to perform this kind of inspection, because the kind of run time type information that is guaranteed to be available is very limited, basically relegated to the type_info structure.
Your compiler/platform may provide additional run-time type information that you can hook into, although the exact types and machinery used to provide RTTI are generally undocumented and difficult to examine (This article by Quarkslab attempts to inspect MSVC's RTTI hierarchy)

C++11: Variadic template deduction logic

I have the following construct:
template <class... Args>
class some_class
{
public:
some_class() = default;
some_class(Args...) = delete;
~some_class() = default;
};
template<>
class some_class<void>
{
public:
some_class() = default;
~some_class() = default;
};
The reason for this is that I just want to allow the users to create objects using the default constructor, so for example:
some_class<int,float> b;
should work but
some_class<int,float> c(1,3.4);
should give me a compilation error.
At some point in time I also needed to create templates based on void hence, the specialization for void:
some_class<void> a;
But by mistake I have typed:
some_class<> d;
And suddenly my code stopped compiling and it gave me the error:
some_class<Args>::some_class(Args ...) [with Args = {}]’ cannot be
overloaded
some_class(Args...) = delete;
So here comes the question: I feel that I am wrong that I assume that some_class<> should be deduced to the void specialization... I just don't know why. Can please someone explain why some_class<> (ie: empty argument list) is different from some_class<void>? (A few lines from the standard will do :) )
https://ideone.com/o6u0D6
void is a type like any other (an incomplete type, to be precise). This means it can be used as a template argument for type template parameters normally. Taking your class template, these are all perfectly valid, and distinct, instantiations:
some_class<void>
some_class<void, void>
some_class<void, void, void>
some_class<void, char, void>
In the first case, the parameter pack Args has one element: void. In the second case, it has two elements: void and void. And so on.
This is quite different from the case some_class<>, in which case the parameter pack has zero elements. You can easily demonstrate this using sizeof...:
template <class... Pack>
struct Sizer
{
static constexpr size_t size = sizeof...(Pack);
};
int main()
{
std::cout << Sizer<>::size << ' ' << Sizer<void>::size << ' ' << Sizer<void, void>::size << std::endl;
}
This will output:
0 1 2
[Live example]
I can't really think of a relevant part of the standard to quote. Perhaps this (C++11 [temp.variadic] 14.5.3/1):
A template parameter pack is a template parameter that accepts zero or more template arguments. [ Example:
template<class ... Types> struct Tuple { };
Tuple<> t0; // Types contains no arguments
Tuple<int> t1; // Types contains one argument: int
Tuple<int, float> t2; // Types contains two arguments: int and float
Tuple<0> error; // error: 0 is not a type
—end example ]

What should I do to add data/values/objects to an initializer list and later send it to a constructor?

So I wanted to practice my skills of using smart pointers. I created a template of class (one-linked list) that has constructor like:
template <class Type>
class list
{
//...
public:
list( std::initializer_list < Type > initlist ) { ... }
//...
};
In main-function I want to construct initializer list and pass it to the class constructor as one thing (smth like this, I think it can be possible but I don't know how to do):
typedef int Type;
int main ()
{
//...
size_t count; // to know How many elements initlist will have
std :: initializer_list < Type > initlist;
cout << "Enter, please, count of elements and their values\n";
cin >> count;
Type temp_data;
for (size_t i = 0; i < count; i++)
{
cin >> temp_data; //user input data and program add it to list
initlist.push_back( temp_data );
// it's wrong. But I found no analogue of "push_back" in std :: initializer_list
// I used push_back to explain what I want to do
}
// ... do stuff
// now I want to pass it to the class object
list < Type > mylist ( initlist ); // or mylist = initlist, or mylist{initlist}
}
I could do smth like below but if I don't know how many and what elements will be input by user then what I should do:
list <Type> mylist {1,2,3,4,5,6,7,8};
So, What should I do to write it correctly? Maybe somebody has an idea.
Thanks.
Usually in C++ containers provide both an std::initializer_list constructor and a constructor that takes two iterators (of any given size) and copies the content of that "range" into the container.
So for example your class could have something like this:
template <class Type>
class list {
//...
public:
list(std::initializer_list<Type> initlist) { ... }
template<typename It>
list(It begin, It end) { ... }
//...
};
In the standard library std::vector, std::list, std::forward_list, std::deque and other containers all support those.
This is done so that if a user knows the elements he/she wants to insert into the container at the moment the container is created he/she uses the std::initializer_list overload. Otherwise if he/she has some other dynamically built container, he can just import the elements in your container.
There is no such thing as a dynamically-sized std::initializer_list. That class is supposed to be lightweight and simple.
You could instead implement push_back or push_front for your list class and build it up incrementally.
The analogue to your current idea would be to build up a std::vector or similar, then provide a constructor which takes an iterator range to copy from that container.

How to store functional objects with different signatures in modern C++

I would like to know if there is a way to store functional objects (functions, callbacks, ...) with different signatures in a standard container (std::map) with modern C++ only. The library that manages the container does not know which signatures will be used by its "clients".
My need is the same as exposed here : How to store functional objects with different signatures in a container?, and this solution https://stackoverflow.com/a/8304873/4042960 is about perfect for me: I would just like to do the same thing without boost. As far as I know, there is no std::any. The best solution for me would be to store std::function without specialized them, but I do not know how to do it, if it is possible.
Edit:
With the answers you give to me I wrote this example :
#include <map>
#include <memory>
#include <functional>
#include <string>
#include <iostream>
#include <stdexcept>
class FunctionMap
{
struct Base {
virtual ~Base() {}
};
template<class R, class... Args>
struct Func : Base
{
std::function<R(Args...)> f;
};
std::map<std::string, std::shared_ptr<Base> > _map;
public:
template<class R, class... Args>
void store(const std::string &key, const std::function<R(Args...)> &f) {
auto pfunc = std::make_shared<Func<R, Args...> >();
pfunc->f = f;
_map.insert(std::make_pair(key, pfunc));
}
template<class R, class... Args>
std::function<R(Args...)> get(const std::string &key) {
auto pfunc = std::dynamic_pointer_cast<Func<R, Args...> >(_map[key]);
if (pfunc)
return pfunc->f;
else
throw std::runtime_error("Bad type for function's parameters");
}
};
// test
int plus(int a, int b) { return a+b; }
double multiplies(double x, double y) { return x*y; }
int main()
{
FunctionMap fm;
fm.store("plus", std::function<int(int, int)>(&plus));
fm.store("multiplies", std::function<double(double, double)>(&multiplies));
// fm.store("square", std::bind(&multiplies, std::placeholders::_1, std::placeholders::_1));
std::cout << "5 + 3 = " << fm.get<int, int, int>("plus")(5, 3) << std::endl;
std::cout << "5 * 3 = " << fm.get<double, double, double>("multiplies")(5.0, 3.0) << std::endl;
return 0;
}
This works well, but I would like to improve it a bit:
1) I would like to be able to use std::bind : fm.store("square", std::bind(&multiplies, std::placeholders::_1, std::placeholders::_1)); but currently that does not compile ;
2) I would like to use fm.get<int (int, int)>("plus") instead of fm.get<int, int, int>("plus") but I do not know how to do it.
Many thanks for your help !
You can write your own any. Without all the compiler workarounds and stuff, boost::any can be written in about 30 lines of code.
Function objects are in no way different from any other kind of objects, so anything applicable to objects in general is applicable to function objects.
So you want to store different kinds of (function) objects in a map. This is normally done by storing (smart) pointers to a base class, where each derived class holds its own kind of objects you want to store.
struct Base {
virtual ~Base(){}
};
template <typename A>
struct Object : Base {
A value;
};
That's your basic caveman's boost::any. Your clients do something like this:
Base* b = mymap["foo"];
dynamic_cast<Object<void(*)(int)>*>(b)->val(123);
But with appropriate checks of course.

Resources