Refactoring read write accessors from/to one data member - c++

I would like to refactor the accessors in following structure:
template<class T>
class ValueTime {
public:
// accessors for val:
const T& get_val() const { return val; }
template<class V> void set_val(const V& v) { val = v; }
// other accessors for tp
private:
T val;
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
};
I would like to make the accessors to the val data members more useful and intuitive, mostly from the point of view of the "standard/boost user expectations" of such structure representing a "value in time":
template<class V = T> V get_val() { return V(val); }
T& operator*() & { return val; }
const T& operator*() const & { return val; }
Now I can use the accessors this way (see the comments):
int main() {
ValueTime<double> vt;
// get_val() no longer returns const ref and also
// allows explicit cast to other types
std::chrono::minutes period{vt.get_val<int>()}; // I had to use the more pedantic static_cast<int> with the original version
// let's use operator*() for getting a ref.
// I think that for a structure like a ValueTime structure,
// it's clear that we get a ref to the stored "value"
// and not to the stored "time_point"
auto val = *vt; // reference now;
val = 42;
}
Is the getter more usueful now? Do you see anything strange or unsafe or counterintuitive in the new interface (apart from being non backward compatible, which I do not care)?
Furthermore, one doubt I still have is if it's better to implement get_val() by returning V(val) or V{val} or just val. As it is now, it works if V has an explicit constructor. What do you think about this issue?

I personally would advise you to make the interface as descriptive as possible and avoid any convenient conversions to reference of data or similar.
The reason is simply usability and maintenance. If you or somebody else are (re-)visiting code using ValueTime, when you cannot remember the precise interface, you still want to understand your code without re-visiting the definition of ValueTime.
There is a difference to members from std (such as std::vector) is that you know their definition by heart.

Related

const correctness for custom reference wrapper

I'm using boost::variant to implement type erasure when sending data across network. When the data arrives to the client or server, I'm inspecting its structure to retrieve the underlying information and reporting errors when the structure does not match the one agreed upon in the API. For this purpose, I created a lightweight reference wrapper that holds a reference to the variant and provides a convenient interface for structure inspection and type conversions.
using value_t = boost::make_recursive_variant< /*types, some of them recursive*/ >::type;
class view_t {
public:
/*non-const methods to access value_*/
private:
value_t& value_;
};
class cview_t {
public:
/*const methods to access value_*/
private:
const value_t& value_;
};
view_t view(value_t& v){ return v; }
cview_t cview(const value_t& v){ return v; }
cview_t cview(value_t&& v) = delete;
cview_t cview(const value_t&& v) = delete;
Unfortunately, this interface proves to be cumbersome because every aggregate type that has a view member needs to follow the same const/non-const split. I was wondering whether it was legal to merge these two classes into a single view and use a const_cast in the methods that create views like this:
class view_t {
public:
/*const and non-const methods to access value_*/
private:
value_t& value_;
};
view_t view(value_t& v){ return v; }
const view_t cview(const value_t& v){ return const_cast<value_t&>(v); }
const view_t cview(value_t&& v) = delete;
const view_t cview(const value_t&& v) = delete;
Returning const object is mostly useless, as
auto /*view_t*/ my_view = cview(some_value); // legal
So you lose your constness.
Modifying const value is undefined behavior,
your view can be used in a way leading to UB.
But as long you don't modify const object, you are "fine".
Splitting into 2 classes is safer, as it cannot be misused.

Avoid literally duplicating code for const and non-const with auto keyword?

Okay, I did some research and apparently there are a lot of duplicate questions on SO on this topic, to name a few:
Elegant solution to duplicate, const and non-const, getters?
How to avoid operator's or method's code duplication for const and non-const objects?
How do I remove code duplication between similar const and non-const member functions?
etc. But I cannot help but raise this again, because
With c++14 auto-typed return value, I am literally duplicating the function body with the only difference being the const function qualifier.
It is possible that const version and non-const version may return types that are totally incompatible from each other. In such cases, neither Scott Meyers's const_cast idiom, nor the "private const function returning non-const" technique would work.
As an example:
struct A {
std::vector<int> examples;
auto get() { return examples.begin(); }
auto get() const { return examples.begin(); }
}; // Do I really have to duplicate?
// My real-world code is much longer
// and there are a lot of such get()'s
In this particular case, auto get() returns an iterator while auto get() const returns a const_iterator, and the two cannot be converted into each other (I know erase(it,it) trick does the conversion in this case but that's not the point). The const_cast hence does not work; even if it works, that requires the programmer to manually deduce auto type, totally defeating the purpose of using auto.
So is there really no way except with macros?
Ok, so after a bit of tinkering I came up with the following two solutions that allow you to keep the auto return type and only implement the getter once. It uses the opposite cast of what Meyer's does.
C++ 11/14
This version simply returns both versions in the implemented function, either with cbegin() or if you don't have that for your type this should work as a replacement for cbegin(): return static_cast<const A&>(*this).examples.begin(); Basically cast to constant and use the normal begin() function to obtain the constant one.
// Return both, and grab the required one
struct A
{
private:
// This function does the actual getter work, hiding the template details
// from the public interface, and allowing the use of auto as a return type
auto get_do_work()
{
// Your getter logic etc.
// ...
// ...
// Return both versions, but have the other functions extract the required one
return std::make_pair(examples.begin(), examples.cbegin());
}
public:
std::vector<int> examples{ 0, 1, 2, 3, 4, 5 };
// You'll get a regular iterator from the .first
auto get()
{
return get_do_work().first;
}
// This will get a const iterator
auto get() const
{
// Force using the non-const to get a const version here
// Basically the inverse of Meyer's casting. Then just get
// the const version of the type and return it
return const_cast<A&>(*this).get_do_work().second;
}
};
C++ 17 - Alternative with if constexpr
This one should be better since it only returns one value and it is known at compile time which value is obtained, so auto will know what to do. Otherwise the get() functions work mostly the same.
// With if constexpr
struct A
{
private:
// This function does the actual getter work, hiding the template details
// from the public interface, and allowing the use of auto as a return type
template<bool asConst>
auto get_do_work()
{
// Your getter logic etc.
// ...
// ...
if constexpr (asConst)
{
return examples.cbegin();
// Alternatively
// return static_cast<const A&>(*this).examples.begin();
}
else
{
return examples.begin();
}
}
public:
std::vector<int> examples{ 0, 1, 2, 3, 4, 5 };
// Nothing special here, you'll get a regular iterator
auto get()
{
return get_do_work<false>();
}
// This will get a const iterator
auto get() const
{
// Force using the non-const to get a const version here
// Basically the inverse of Meyer's casting, except you get a
// const_iterator as a result, so no logical difference to users
return const_cast<A&>(*this).get_do_work<true>();
}
};
This may or may not work for your custom types, but it worked for me, and it solves the need for code duplication, although it uses a helper function. But in turn the actual getters become one-liners, so that should be reasonable.
The following main function was used to test both solutions, and worked as expected:
int main()
{
const A a;
*a.get() += 1; // This is an error since it returns const_iterator
A b;
*b.get() += 1; // This works fine
std::cout << *a.get() << "\n";
std::cout << *b.get() << "\n";
return 0;
}
struct A {
std::vector<int> examples;
private:
template <typename ThisType>
static auto
get_tmpl(ThisType& t) { return t.examples.begin(); }
public:
auto get() { return get_tmpl(*this); }
auto get() const { return get_tmpl(*this); }
};
How about the above? Yes, you still need to declare both methods, but the logic can be contained in a single static template method. By adding a template parameter for return type this will work even for pre-C++11 code.
Just a hypothetical solution, that I am thinking about applying every where once we will have concepts: using friend free function in place of member function.
//Forwarding ref concept
template<class T,class U>
concept FRef = std::is_same_v<std::decay_t<T>,std::decay_t<U>>;
struct A{
std::vector<int> examples;
friend decltype(auto) get(FRef{T,A}&& aA){
return std::forward<T>(aA).examples.begin();
//the std::forward is actualy not necessary here
//because there are no overload value reference overload of begin.
}
};

shared_ptr<T> to shared_ptr<T const> and vector<T> to vector<T const>

I'm trying to define a good design for my software which implies being careful about read/write access to some variables. Here I simplified the program for the discussion. Hopefully this will be also helpful to others. :-)
Let's say we have a class X as follow:
class X {
int x;
public:
X(int y) : x(y) { }
void print() const { std::cout << "X::" << x << std::endl; }
void foo() { ++x; }
};
Let's also say that in the future this class will be subclassed with X1, X2, ... which can reimplement print() and foo(). (I omitted the required virtual keywords for simplicity here since it's not the actual issue I'm facing.)
Since we will use polymorphisme, let's use (smart) pointers and define a simple factory:
using XPtr = std::shared_ptr<X>;
using ConstXPtr = std::shared_ptr<X const>;
XPtr createX(int x) { return std::make_shared<X>(x); }
Until now, everything is fine: I can define goo(p) which can read and write p and hoo(p) which can only read p.
void goo(XPtr p) {
p->print();
p->foo();
p->print();
}
void hoo(ConstXPtr p) {
p->print();
// p->foo(); // ERROR :-)
}
And the call site looks like this:
XPtr p = createX(42);
goo(p);
hoo(p);
The shared pointer to X (XPtr) is automatically converted to its const version (ConstXPtr). Nice, it's exactly what I want!
Now come the troubles: I need a heterogeneous collection of X. My choice is a std::vector<XPtr>. (It could also be a list, why not.)
The design I have in mind is the following. I have two versions of the container: one with read/write access to its elements, one with read-only access to its elements.
using XsPtr = std::vector<XPtr>;
using ConstXsPtr = std::vector<ConstXPtr>;
I've got a class that handles this data:
class E {
XsPtr xs;
public:
E() {
for (auto i : { 2, 3, 5, 7, 11, 13 }) {
xs.emplace_back(createX(std::move(i)));
}
}
void loo() {
std::cout << "\n\nloo()" << std::endl;
ioo(toConst(xs));
joo(xs);
ioo(toConst(xs));
}
void moo() const {
std::cout << "\n\nmoo()" << std::endl;
ioo(toConst(xs));
joo(xs); // Should not be allowed
ioo(toConst(xs));
}
};
The ioo() and joo() functions are as follow:
void ioo(ConstXsPtr xs) {
for (auto p : xs) {
p->print();
// p->foo(); // ERROR :-)
}
}
void joo(XsPtr xs) {
for (auto p: xs) {
p->foo();
}
}
As you can see, in E::loo() and E::moo() I have to do some conversion with toConst():
ConstXsPtr toConst(XsPtr xs) {
ConstXsPtr cxs(xs.size());
std::copy(std::begin(xs), std::end(xs), std::begin(cxs));
return cxs;
}
But that means copying everything over and over.... :-/
Also, in moo(), which is const, I can call joo() which will modify xs's data. Not what I wanted. Here I would prefer a compilation error.
The full code is available at ideone.com.
The question is: is it possible to do the same but without copying the vector to its const version? Or, more generally, is there a good technique/pattern which is both efficient and easy to understand?
Thank you. :-)
I think the usual answer is that for a class template X<T>, any X<const T> could be specialized and therefore the compiler is not allow to simply assume it can convert a pointer or reference of X<T> to X<const T> and that there is not general way to express that those two actually are convertible. But then I though: Wait, there is a way to say X<T> IS A X<const T>. IS A is expressed via inheritance.
While this will not help you for std::shared_ptr or standard containers, it is a technique that you might want to use when you implement your own classes. In fact, I wonder if std::shared_ptr and the containers could/should be improved to support this. Can anyone see any problem with this?
The technique I have in mind would work like this:
template< typename T > struct my_ptr : my_ptr< const T >
{
using my_ptr< const T >::my_ptr;
T& operator*() const { return *this->p_; }
};
template< typename T > struct my_ptr< const T >
{
protected:
T* p_;
public:
explicit my_ptr( T* p )
: p_(p)
{
}
// just to test nothing is copied
my_ptr( const my_ptr& p ) = delete;
~my_ptr()
{
delete p_;
}
const T& operator*() const { return *p_; }
};
Live example
There is a fundamental issue with what you want to do.
A std::vector<T const*> is not a restriction of a std::vector<T*>, and the same is true of vectors containing smart pointers and their const versions.
Concretely, I can store a pointer to const int foo = 7; in the first container, but not the second. std::vector is both a range and a container. It is similar to the T** vs T const** problem.
Now, technically std::vector<T const*> const is a restriction of std::vector<T>, but that is not supported.
A way around this is to start workimg eith range views: non owning views into other containers. A non owning T const* iterator view into a std::vector<T *> is possible, and can give you the interface you want.
boost::range can do the boilerplate for you, but writing your own contiguous_range_view<T> or random_range_view<RandomAccessIterator> is not hard. It gets fancy ehen you want to auto detect the iterator category and enable capabilities based off that, which is why boost::range contains much more code.
Hiura,
I've tried to compile your code from repo and g++4.8 returned some errors.
changes in main.cpp:97 and the remaining lines calling view::create() with lambda function as the second argument.
+add+
auto f_lambda([](view::ConstRef_t<view::ElementType_t<Element>> const& e) { return ((e.getX() % 2) == 0); });
std::function<bool(view::ConstRef_t<view::ElementType_t<Element>>)> f(std::cref(f_lambda));
+mod+
printDocument(view::create(xs, f));
also View.hpp:185 required additional operator, namely:
+add+
bool operator==(IteratorBase const& a, IteratorBase const& b)
{
return a.self == b.self;
}
BR,
Marek Szews
Based on the comments and answers, I ended up creating a views for containers.
Basically I defined new iterators. I create a project on github here: mantognini/ContainerView.
The code can probably be improved but the main idea is to have two template classes, View and ConstView, on an existing container (e.g. std::vector<T>) that has a begin() and end() method for iterating on the underlying container.
With a little bit of inheritance (View is a ConstView) it helps converting read-write with to read-only view when needed without extra code.
Since I don't like pointers, I used template specialization to hide std::shared_ptr: a view on a container of std::shared_ptr<T> won't required extra dereferencing. (I haven't implemented it yet for raw pointers since I don't use them.)
Here is a basic example of my views in action.

How to create operator-> in iterator without a container?

template <class Enum>
class EnumIterator {
public:
const Enum* operator-> () const {
return &(Enum::OfInt(i)); // warning: taking address of temporary
}
const Enum operator* () const {
return Enum::OfInt(i); // There is no problem with this one!
}
private:
int i;
};
I get this warning above. Currently I'm using this hack:
template <class Enum>
class EnumIterator {
public:
const Enum* operator-> () {
tmp = Enum::OfInt(i);
return &tmp;
}
private:
int i;
Enum tmp;
};
But this is ugly because iterator serves as a missing container.
What is the proper way to iterate over range of values?
Update:
The iterator is specialized to a particular set objects which support named static constructor OfInt (code snippet updated).
Please do not nit-pick about the code I pasted, but just ask for clarification. I tried to extract a simple piece.
If you want to know T will be strong enum type (essentially an int packed into a class). There will be typedef EnumIterator < EnumX > Iterator; inside class EnumX.
Update 2:
consts added to indicate that members of strong enum class that will be accessed through -> do not change the returned temporary enum.
Updated the code with operator* which gives no problem.
Enum* operator-> () {
tmp = Enum::OfInt(i);
return &tmp;
}
The problem with this isn't that it's ugly, but that its not safe. What happens, for example in code like the following:
void f(EnumIterator it)
{
g(*it, *it);
}
Now g() ends up with two pointers, both of which point to the same internal temporary that was supposed to be an implementation detail of your iterator. If g() writes through one pointer, the other value changes, too. Ouch.
Your problem is, that this function is supposed to return a pointer, but you have no object to point to. No matter what, you will have to fix this.
I see two possibilities:
Since this thing seems to wrap an enum, and enumeration types have no members, that operator-> is useless anyway (it won't be instantiated unless called, and it cannot be called as this would result in a compile-time error) and can safely be omitted.
Store an object of the right type (something like Enum::enum_type) inside the iterator, and cast it to/from int only if you want to perform integer-like operations (e.g., increment) on it.
There are many kind of iterators.
On a vector for example, iterators are usually plain pointers:
template <class T>
class Iterator
{
public:
T* operator->() { return m_pointer; }
private:
T* m_pointer;
};
But this works because a vector is just an array, in fact.
On a doubly-linked list, it would be different, the list would be composed of nodes.
template <class T>
struct Node
{
Node* m_prev;
Node* m_next;
T m_value;
};
template <class T>
class Iterator
{
public:
T* operator->() { return m_node->m_value; }
private:
Node<T>* m_node;
};
Usually, you want you iterator to be as light as possible, because they are passed around by value, so a pointer into the underlying container makes sense.
You might want to add extra debugging capabilities:
possibility to invalidate the iterator
range checking possibility
container checking (ie, checking when comparing 2 iterators that they refer to the same container to begin with)
But those are niceties, and to begin with, this is a bit more complicated.
Note also Boost.Iterator which helps with the boiler-plate code.
EDIT: (update 1 and 2 grouped)
In your case, it's fine if your iterator is just an int, you don't need more. In fact for you strong enum you don't even need an iterator, you just need operator++ and operator-- :)
The point of having a reference to the container is usually to implement those ++ and -- operators. But from your element, just having an int (assuming it's large enough), and a way to get to the previous and next values is sufficient.
It would be easier though, if you had a static vector then you could simply reuse a vector iterator.
An iterator iterates on a specific container. The implementation depends on what kind of container it is. The pointer you return should point to a member of that container. You don't need to copy it, but you do need to keep track of what container you're iterating on, and where you're at (e.g. index for a vector) presumably initialized in the iterator's constructor. Or just use the STL.
What does OfInt return? It appears to be returning the wrong type in this case. It should be returning a T* instead it seems to be returning a T by value which you are then taking the address of. This may produce incorrect behavior since it will loose any update made through ->.
As there is no container I settled on merging iterator into my strong Enum.
I init raw int to -1 to support empty enums (limit == 0) and be able to use regular for loop with TryInc.
Here is the code:
template <uint limit>
class Enum {
public:
static const uint kLimit = limit;
Enum () : raw (-1) {
}
bool TryInc () {
if (raw+1 < kLimit) {
raw += 1;
return true;
}
return false;
}
uint GetRaw() const {
return raw;
}
void SetRaw (uint raw) {
this->raw = raw;
}
static Enum OfRaw (uint raw) {
return Enum (raw);
}
bool operator == (const Enum& other) const {
return this->raw == other.raw;
}
bool operator != (const Enum& other) const {
return this->raw != other.raw;
}
protected:
explicit Enum (uint raw) : raw (raw) {
}
private:
uint raw;
};
The usage:
class Color : public Enum <10> {
public:
static const Color red;
// constructors should be automatically forwarded ...
Color () : Enum<10> () {
}
private:
Color (uint raw) : Enum<10> (raw) {
}
};
const Color Color::red = Color(0);
int main() {
Color red = Color::red;
for (Color c; c.TryInc();) {
std::cout << c.GetRaw() << std::endl;
}
}

Is there C++ lazy pointer?

I need a shared_ptr like object, but which automatically creates a real object when I try to access its members.
For example, I have:
class Box
{
public:
unsigned int width;
unsigned int height;
Box(): width(50), height(100){}
};
std::vector< lazy<Box> > boxes;
boxes.resize(100);
// at this point boxes contain no any real Box object.
// But when I try to access box number 50, for example,
// it will be created.
std::cout << boxes[49].width;
// now vector contains one real box and 99 lazy boxes.
Is there some implementation, or I should to write my own?
It's very little effort to roll your own.
template<typename T>
class lazy {
public:
lazy() : child(0) {}
~lazy() { delete child; }
T &operator*() {
if (!child) child = new T;
return *child;
}
// might dereference NULL pointer if unset...
// but if this is const, what else can be done?
const T &operator*() const { return *child; }
T *operator->() { return &**this; }
const T *operator->() const { return &**this; }
private:
T *child;
};
// ...
cout << boxes[49]->width;
Using boost::optional, you can have such a thing:
// 100 lazy BigStuffs
std::vector< boost::optional<BigStuff> > v(100);
v[49] = some_big_stuff;
Will construct 100 lazy's and assign one real some_big_stuff to v[49]. boost::optional will use no heap memory, but use placement-new to create objects in a stack-allocated buffer. I would create a wrapper around boost::optional like this:
template<typename T>
struct LazyPtr {
T& operator*() { if(!opt) opt = T(); return *opt; }
T const& operator*() const { return *opt; }
T* operator->() { if(!opt) opt = T(); return &*opt; }
T const* operator->() const { return &*opt; }
private:
boost::optional<T> opt;
};
This now uses boost::optional for doing stuffs. It ought to support in-place construction like this one (example on op*):
T& operator*() { if(!opt) opt = boost::in_place(); return *opt; }
Which would not require any copy-ing. However, the current boost-manual does not include that assignment operator overload. The source does, however. I'm not sure whether this is just a defect in the manual or whether its documentation is intentionally left out. So i would use the safer way using a copy assignment using T().
I've never heard of such a thing, but then again there are lots of things I've never heard of. How would the "lazy pointer" put useful data into the instances of the underlying class?
Are you sure that a sparse matrix isn't what you're really looking for?
So far as I know, there's no existing implementation of this sort of thing. It wouldn't be hard to create one though.