Consider I have some simple class:
template<typename T>
class Vector {
public:
T first() const { return this->m_first; }
T second() const { return this->m_second; }
private:
T m_first;
T m_second;
}
Now I want to create some meaning behind some of that:
typedef Vector<int> Position;
typedef Vector<unsigned int> Dimension;
Can I also create an alias to the methods of the new types Position and Dimension so that for Position, x() references frist(), y() references second() while for Dimension width() references first(), height() references second().
Or even more "speedy": Having first and second public, create aliases to the member variables? Real use case is more complex, but this should display what I want: Two things that are very similar in memory, but called completly different depending on the context.
You can achieve what you want by doing something like this:
class Position : private Vector<int> {
public:
auto x() const { return first(); }
auto y() const { return second(); }
};
class Dimension : private Vector<unsigned int> {
public:
auto width() const { return first(); }
auto height() const { return second(); }
};
which creates new types that inherit from a specific instantiation of Vector, and call the privately inherited member functions with publicly accessible meaningful names.
Here's a demo.
Related
I have these generic classes for 2D geometry:
template<class T> struct Point
{
T x,y;
//...Various member functions...
//T modulus() const noexcept { ... }
//T dist_from(const Point& other) const noexcept { ... }
//...
};
template<class T> class Polygon
{
public:
// ...An awful lot of member functions...
auto size() const noexcept { return vertexes.size(); }
//T area() const noexcept {...}
//T perimeter() const noexcept {...}
//T moment_of_inertia(const Point<T>&) const noexcept {...}
//void reorder_vertexes() {...}
//void transform(const Matrix& m) {...}
// ...
private:
std::vector<Point<T>> vertexes;
};
They work well and I use them in various part of the project. Now, for a particular application, I need Polygon but also need to associate some data to each of its vertexes.
Since Polygon vertexes can be transformed and reordered I would prefer to avoid the extra work of maintaining a parallel std::vector containing the additional data.
I would really like to introduce a new class like this:
template<class T, class D> class DecoratedPolygon
{
public:
struct DecoratedPoint
{
Point<T> point;
D data;
};
// Some specialized member functions...
const D& get_vertex_decoration(const std::size_t idx) const
{
return vertexes.at(idx).data;
}
// ...Then same member functions as polygon,
// except accessing the '.point'
auto size() const noexcept { return vertexes.size(); }
//...
private:
std::vector<DecoratedPoint> vertexes;
};
My problem whith this is that I don't want to rewrite a slightly modified version of all the member functions of Polygon.
How would you approach this particular case? I wonder if there is a zero cost technique to avoid that code duplication, or if simply I'm heading in the wrong way.
You could try to parameterize the Polygon class to take in the Point type as well:
template <class P> class Polygon {
std::vector<P> vertices
}
template <class T> class Point {
T x,y;
}
class DecoratedPoint : Point<long> {
int extraData;
}
Polygon<DecoratedPoint> newPoly;
The decorated data would end up coming from the point itself though, so the interface would look a bit different:
Polygon {
P get_point_at_idx( const std::size_t idx) {
return points.at(idx)
}
}
my_poly.get_point_at_idx(0).extraData
You'd need to change the implementation of Polygon a bit, but might provide more control longer term.
Assume I have a class A that I want to store in an unordered_set with custom hasher and comparer. I also have a container class B that stores this set:
class B {
private:
std::unordered_set<A, Hasher, Comparer> set;
};
To make this compile I would have to make B a template class, which I want to avoid, as this would lead to some major refactoring and actually moves this problem just a layer up where I would then have to handle template parameters for B.
Next I tried to make class that specialize the set:
class MySet1 : public std::unordered_set<A, MyHasher1, MyComparer1> {
};
class MySet2 : public std::unordered_set<A, MyHasher2, MyComparer2> {
};
Obviously that doesn't help as I still have no common base class for my set var in class B.
To solve this I moved down the unordered set one level:
class MySet {
public:
// Some abstract functions...
};
class MySet1 : public MySet {
public:
// Implementation of the abstract functions.
private:
std::unordered_set<A, MyHasher1, MyComparer1> set;
};
class MySet2 : public MySet {
public:
// Implementation of the abstract functions.
private:
std::unordered_set<A, MyHasher2, MyComparer2> set;
};
Now I have a common base class (MySet) for class B. But the obvious disadvantages are: code duplication for each set specialization and I would have to imlement custom iterators to make the sets work with the STL. Here's were I stopped and asked myself if there's a better way to accomplish what I actually want: store different unordered_set classes in the same member var without the need to make the owner of that var templated as well.
Main idea
You can happily employ multiple inheritance here.
The main idea is: create a base class tagging your sets and make it a base class for all your sets. Then explicitly instantiate the set class for each template arguments you need, creating an empty class inherited publicly from both the set container and your tagging interface. Then you'll have nothing to add, no code duplication seems to be needed.
Anyway, you'll need to create some (maybe virtual) functions that will work for all template specializations. We'll need to be able to use a single variable in the same context regardless of what it holds. But you can try reduce some code with more using declarations due to inheritance and use implicit type conversion (e.g. if your sets contain numbers only).
#include <set>
class setInterface {
/* Code common for all set template specializations
(you have to have some common interface anyway) */
};
template <typename T> class TSet: public setInterface, std::set<T> {
using std::set<T>::set;
/* more using-declarations or templated versions of some functions
You can use SFINAE here to achieve more magical results,
or use template specializations for specific types. */
};
using intSet = TSet<int>;
using doubleSet = TSet<double>;
class B {
public:
setInterface values;
};
int main () {
B b;
b.values = intSet {1, 2, 3} ;
b.values = doubleSet {1., 2., 3.};
}
PS: thanks go to #Jarod42 for the template using syntax.
A working implementation
The following assumptions have been made:
We will use only the sets with items convertible to long long. We can use void* in general case and add some additional methods for convenience/safety.
We are sane and will never compare iterators of differently typed sets. The results will be unpredictable.
We don't need to check pointers for nullptrs (well, it will bring no more value in my code sample, sure in real world you always need).
The solution is able to iterate over the map using non-const begin/ends and using the new shiny range-based for. See the main; compile and run it (-std=c++14) to see the result.
#include <set>
#include <memory>
#include <iostream>
using common_denominator_type = long long;
class setInterface {
protected:
class iterator_impl;
public:
class iterator {
public:
iterator (iterator_impl* impl) : impl (impl) {}
iterator& operator++ () { ++*impl; return *this; };
bool operator != (const iterator& rhs) const { return *impl != *rhs.impl; };
common_denominator_type operator* () const { return **impl; };
private:
std::shared_ptr <iterator_impl> impl;
};
virtual iterator begin() = 0;
virtual iterator end() = 0;
virtual size_t size() const = 0;
protected:
class iterator_impl {
public:
virtual iterator_impl& operator++ () = 0;
virtual bool operator != (const iterator_impl&) const = 0;
virtual common_denominator_type operator* () const = 0;
virtual void* as_std_set_iterator () = 0;
virtual const void* as_std_set_iterator () const = 0;
};
};
template <typename T> class TSet: public setInterface, std::set<T> {
public:
using std::set<T>::set;
size_t size () const override { return std::set<T>::size(); }
iterator begin () override { return iterator (new TSet<T>::iterator_impl (std::set<T>::begin())); }
iterator end () override { return iterator (new TSet<T>::iterator_impl (std::set<T>::end ())); }
protected:
class iterator_impl: public setInterface::iterator_impl {
public:
using std_it = typename std::set<T>::iterator;
iterator_impl (std_it&& _) : m_real_iterator(std::move (_)) {}
iterator_impl& operator++ () override { ++m_real_iterator; return *this; }
bool operator != (const setInterface::iterator_impl& rhs) const override {
return *reinterpret_cast <const std_it*>(as_std_set_iterator())
!=
*reinterpret_cast <const std_it*>(rhs.as_std_set_iterator());
}
common_denominator_type operator* () const override { return *m_real_iterator; }
void* as_std_set_iterator () override { return &m_real_iterator; }
const void* as_std_set_iterator () const override { return &m_real_iterator; }
private:
std_it m_real_iterator;
};
};
using intSet = TSet<int>;
using longSet = TSet<long>;
class B {
public:
std::shared_ptr <setInterface> values;
};
std::ostream& operator<< (std::ostream& str, B& b) {
str << "[" << b.values->size() << "] [";
for (auto i = b.values->begin(); i != b.values->end(); ++i)
str << *i << " ";
str << "][";
for (auto i : *b.values)
str << i << " ";
return str << "]";
}
int main () {
B b;
b.values.reset (new intSet {1, 2, 3});
std::cout << b << std::endl;
b.values.reset (new longSet {10l, 20l, 30l});
std::cout << b << std::endl;
}
I am making a class that shares data between several objects using dynamic memory. The relevant parts of the class are shown below.
class StrBlob
{
public:
StrBlob::StrBlob(std::initializer_list<std::string> il) :
data(std::make_shared<std::vector<std::string>>(il)) {}
void push_back(const std::string &t) const { data->push_back(t); }
private:
std::shared_ptr<std::vector<std::string>> dataPtr;
};
I understand that by making push_back a const member function, I am saying that this function will not change the member dataPtr. However, the underlying vector that dataPtr points to is not const, as shown by the below code.
//The result is foo = {"bar", "foobar"}
const StrBlob foo = {"bar"};
foo.push_back("foobar");
Is it possible or even desirable to make the underlying vector const by making the StrBlob object const? Should be something like making dataPtr a pointer to const when the object is const, but I'm not sure how to achieve that.
You can make a thin wrapper around std::shared_ptr (details omitted like ctor etc):
#include <memory>
template< class T > class const_propagated_shared_ptr {
std::shared_ptr<T> m_ptr;
public:
T &operator*() { return m_ptr.operator*(); }
T* operator->() { return m_ptr.operator->(); }
const T &operator*() const { return m_ptr.operator*(); }
const T *operator->() const { return m_ptr.operator->(); }
};
class Foobar {
const_propagated_shared_ptr<int> m_ptr;
public:
void f1() { *m_ptr = 10; }
void f2() const { *m_ptr = 10; } // compile error
};
But as this is implementation detail of the class (Foobar in this case) I am not sure that it worse the effort, as to let modify data by const method or not can be controlled by class designer.
In C++ I'm often facing a situation when I need to prepare const and non-const version of class in analogy to const_iterator and iterator from standard library.
class const_MyClass
{
public:
const_MyClass(const int * arr):
m_arr(arr)
{
}
int method() const; //does something with m_arr without modifying it
private:
const int * m_arr;
}
class MyClass
{
public:
MyClass(int * arr):
m_arr(arr)
{
}
int method() const; //does something with m_arr without modifying it
void modify(int i); //modify m_arr
private:
int * m_arr;
}
The problem with this is that I need to repeat whole code of const_MyClass in MyClass and distribute any changes in API to both classes. Thus sometimes I inherit const_MyClass and do some const_casts, which also isn't perfect and pretty solution. Still when I want to pass const_MyClass instance by reference it looks moronic:
void func(const const_MyClass & param)
Instance param is marked with two "consts", and it has only const methods...
This is where const constructors would be handy, but are there any existing alternatives?
Some use examples to explain problem better:
//ok to modify data
void f(int * data)
{
MyClass my(data);
my.modify();
...
}
//cant modify data, cant use MyClass
void fc(const int * data)
{
const_MyClass my(data);
int i = my.method();
...
}
You can make a template class to act as a base, like this:
template<typename T>
class basic_MyClass
{
public:
basic_MyClass(T * arr) :m_arr(arr) {}
int method() const; //does something with m_arr without modifying it
private:
T * m_arr;
};
Then, for your const version, since it doesn't add anything, you can just use a typedef:
typedef basic_MyClass<const int> const_MyClass;
For your non-const version, you can inherit:
class MyClass : public basic_MyClass<int>
{
public:
using basic_MyClass::basic_MyClass; // inherit all the constructors
void modify(int i); //modify m_arr
};
Have you considered simply tracking two pointers and raising exceptions from the mutable operations when no mutable value is available? Maybe an example will help describe what I am thinking of.
class MyClass
{
public:
MyClass(int *mutable_data):
m_mutable_view(mutable_data), m_readonly_view(mutable_data)
{
}
MyClass(const int *immutable_data):
m_mutable_view(NULL), m_readonly_view(immutable_data)
{
}
int retrieve_value(int index) {
return m_readonly_view[index];
}
void set_value(int index, int value) {
require_mutable();
m_mutable_view[index] = value;
}
protected:
void require_mutable() {
throw std::runtime_error("immutable view not available");
}
private:
const int *m_readonly_view;
int *m_mutable_view;
};
The idea is pretty simple here - use a sentinel value to indicate whether modifications are possible or not instead of depending on the type system to do that for you. Personally, I would think about doing the inheritance based approach that #BenjaminLindley suggested but I wanted to present a slightly different solution that might not have occurred to you.
After talk with Neil Kirk I realized what I was doing wrong. I started by separating data from logic as he suggested.
This attempt resulted in two classes MyClassPtr and const_MyClassPtr. They only provide functions for data access (like iterators) and may look like that:
class const_MyClassPtr
{
public:
const_MyClassPtr(const int * arr);
int operator [](int i) const;
const int * ptr() const;
private:
const int * m_arr;
}
class MyClassPtr
{
public:
MyClassPtr(int * arr);
int operator [](int i) const;
int & operator [](int i);
const int * ptr() const;
int * ptr();
//promotion to const pointer
const_MyClassPtr () const {return const_MyClassPtr(m_arr);}
private:
int * m_arr;
}
Now it is clear that objects of these classes should be treated like pointers, so when I use them as function parameters I pass them by value!
void func(const_MyClassPtr param) //instead of void func(const const_MyClass & param)
To provide methods I have created MyClassOp class template and used static polymorphism.
template <class DERIVED>
class MyClassOp
{
public:
const DERIVED & derived() const {return static_cast<const DERIVED &>(*this)}
DERIVED & derived() {return static_cast<DERIVED &>(*this)}
int method() const; //operates on derived() const
void modify(int i); //operates on derived()
}
MyClassOp is a collection of methods. It does not have state. In general it is a trait. To make these methods accessible I overloaded -> and * operators
class const_MyClassPtr : private MyClassOp<const_MyClassPtr>
{
public:
const MyClassOp<MyClassPtr> * operator ->() const {return this;}
const MyClassOp<MyClassPtr> & operator *() const {return *this;}
...
}
class MyClassPtr : private MyClassOp<MyClassPtr>
{
public:
MyClassOp<MyClassPtr> * operator ->() {return this;}
MyClassOp<MyClassPtr> & operator *() {return *this;}
...
}
This works O.K., but is a bit cumbersome. If I have for example equality operator I need to write something like *myptr1 == myptr2 to compare values kept by two MyClassPtr objects (it's easy to make a mistake and compare myptr1 == myptr2 or expect that something like *myptr1 == *myptr2 could work). Also when I have allocating type:
class MyClass : public MyClassOp<MyClass>
{
MyClass(int x, int y, int z);
...
int m_arr[3];
}
I would want to be able to use temporaries as function arguments.
void f(const_MyClassPtr my);
//use temporary when calling f()
f(MyClass(1, 2, 3));
I can do this by providing conversion operators or conversion constructors (that convert MyClass to const_MyClassPtr). But then const_MyClassPtr behaves more like reference than pointer. If iterators are generalization of pointers then why one could not imitate reference? Therefore I divided MyClassOp into two parts (const and non const) and replaced -> and * operators implemented by const_MyClassPtr and MyClassPtr with public inheritance and changed their names to ressemble reference. I ended up with following structures.
MyClassOp : public const_MyClassOp
const_MyClassRef : public const_MyClassOp<const_MyClassRef>
MyClassRef : public MyClassOp<MyClassRef>
MyClass : public MyClassOp<MyClass>
However const_MyClassRef and MyClassRef are not perfect generalization of reference as it impossible to imitate some of C++ reference properties, so Ref suffix is there to denote reference-like structure.
Maybe you can find some hints in effective c++ item 4 "Avoid duplication in const and non-const Member function"
I may summarize like following ( it makes you avoid code duplication even if using somewhat ugly cast ):
struct my_class
{
my_class(int x):_x(x){};
const int& method(void) const;
int& method(void);
int _x;
};
const int& my_class::method(void) const //func for const instance
{
return _x;
}
int& my_class::method(void) //func for normal instance
{
return const_cast<int& >(static_cast<const my_class& >(*this).method()) ;
}
int main()
{
my_class a(1);
const my_class b(2);
a.method() = 5;
cout << a.method() << endl;
//b.method() = 4; //b is const, wont compile
cout << b.method() << endl;
return 0;
}
I'm stuck with this piece of code:
class MyObject
{
public:
int value;
}
class MyClass
{
private:
btAlignedObjectArray<MyObject*> m_objects;
public:
int comp (MyObject *a, MyObject *b)
{
return calculateTheNewValue(a->value) < calculateTheNewValue(b->value);
}
void doSort()
{
m_objects.quickSort(comp);
}
//edit: this member function is needed to do the sorting
int calculateTheNewValue(int v)
{
// do some calculation using other members variables, not necessarily m_objects
}
};
It doesn't compile because comp is a non static member function.
comp cant be static, because it needs to access the member variable m_objects.
Also it would defeat the encapsulation of m_objects to have a static function and call it like this
MyClass::doSort(myClass.m_objects)
Edit
This is the declaration of btAlignedObjectArray
http://bulletphysics.org/Bullet/BulletFull/btAlignedObjectArray_8h_source.html
Line 365 has the declaration or quicksort
If you need to make comp into a binary function, then wrap it in a functor. If you can use C++11, then use a lambda:
m_objects.quickSort([&](MyObject * lhs, MyObject * rhs) {
return this->comp(lhs,rhs)
});
If you can't use C++11, then make a functor class with similar behavior.
struct compare
{
MyObject & obj_;
compare(MyObject& obj) :obj_(obj) {}
bool operator()(MyObject * lhs, MyObject * rhs) const {
return obj_.comp(lhs,rhs);
}
};
...
void doSort()
{
m_objects.quicksort(compare(*this));
}