Design : const and non-const accessors interdependance? [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I remove code duplication between similar const and non-const member functions?
In the following example :
template<typename Type, unsigned int Size>
class MyClass
{
public: inline Type& operator[](const unsigned int i)
{return _data[i];}
public: inline const Type& operator[](const unsigned int i) const
{return _data[i];}
protected: Type _data[Size];
};
the const and non-const operator[] are implemented independently.
In terms of design is it better to have :
1) two independant implementations like here
2) one of the two function calling the other one
If solution 2) is better, what would be the code of the given example ?

It is a well-known and widely accepted implementation pattern, when non-const method is implemented through its const counterpart, as in
class some_class {
const some_type& some_method(arg) const
{
...;
return something;
}
some_type& some_method(arg)
{
return const_cast<some_type&>(
const_cast<const some_class *>(this)->some_method(arg));
}
};
This is a perfectly valid technique, which essentially has no comparable (in convenience) alternatives in situations when the method body is relatively heavy. The evil of const_cast is significantly smaller than the evil of duplicated code.
However, when the body of the method is essentially an one-liner, it might be a better idea to stick to an explicit identical implementation, just to avoid this barely readable pileup of const_casts.
One can probably come up with a formally better designed castless solution implemented along the lines of
class some_class {
template <typename R, typename C>
static R& some_method(C *self, arg)
{
// Implement it here in terms of `self->...` and `R` result type
}
const some_type& some_method(arg) const
{
return some_method<const some_type>(this, arg);
}
some_type& some_method(arg)
{
return some_method<some_type>(this, arg);
}
};
but to me it looks even less elegant than the approach with const_cast.

You couldn't have either implementation calling the other one without casting away constness, which is a bad idea.
The const method can't call the non-const one.
The non-const method shouldn't call the const one because it'd need to cast the return type.

Unfortunately, "constness" templates don't work but I still think it is worth considering the overall idea:
// NOTE: this DOES NOT (yet?) work!
template <const CV>
Type CV& operator[](unsigned int index) CV {
...
}
For the time being, I'd implement trivial functions just twice. If the code become any more complex than a line or two, I'd factor the details into a function template and delegate the implementation.

Related

Constant version of a concept as return type in requires clause

I have some class A that has some const and some non-const function, together with a fitting concept, say
class A {
public:
void modify() {/* ... */}
void print() const {/* ... */}
}
template<typename T>
concept LikeA = requires (T t, const T const_t) {
{ t.modify() } -> std::same_as<void>;
{ const_t.print() } -> std::same_as<void>;
}
static_assert(LikeA<A>);
A nice thing I noticed is that for some function taking const LikeA auto &a below code is actually legal:
void use (const LikeA auto &a) {
a.print(); // fine, print is a const method
// a.modify(); // illegal, a is a const reference [at least for use(A a) itself, but this is not my point here]
}
static_assert(!LikeA<const A>);
int main() {
A a1;
use(a1); //clear, as LikeA<A> holds
const A a2;
use(a2); //not obvious, as LikeA<const A> does not hold
}
I looked into the definitions on cppreference, and I could not really explain this behaviour, I expected it to be illegal, although intuitively, this really is what I want.
Now on to my real situation: I have a holder class AHolder that returns const A& as one of its methods, and I want a fitting concept for this holder class that also applies to any other holder holding anything that satisfies LikeA, so I tried:
class AHolder {
public:
const A& getA() {return _a;}
private:
const A _a;
};
template<typename T>
concept LikeAHolder = requires (T t) {
{t.getA() } -> LikeA;
};
static_assert(LikeAHolder<AHolder>); //fails
This fails, since const A& simply doesn't satisfy LikeA, so i would love to adjust this to
template<typename T>
concept LikeAHolder = requires (T t) {
{t.getA() } -> const LikeA; //invalid syntax
};
static_assert(LikeAHolder<AHolder>);
in similar spirit of the example with the use method also accepting const A.
Is there such a syntax to require the return type of t.getA to satisfy LikeA whilst considering that the return type will be const?
Additionally, how exactly are concepts checked in the use(const LikeA auto &a) method such that it behaves like explained?
(My first question is the more important one for me)
Some possible solutions that I have considered:
Return a non-const-reference. This would make above code illegal, but of course would heavily ruin const-correctness, since _a would also have to be non-const and a user could just change the private attribute of AHolder. This is no option for me.
Have two concepts LikeA and LikeConstA. The return type then could be LikeConstA only requiring the const methods. This should work, but feels really clumsy and really not how concepts should be used, also this introduces more concepts that necessary to an end-user, who has to bother with them, etc.
In the concept LikeA, check whether the templated type T is constant (via std::is_const), and if so, don't require the non-const-methods. This works in above example, but has the undesired effect that we now simply have
class B {
public:
void print() const {/* ... */}
}
static_assert(LikeA<const B>);
(for an already adapted LikeA, of course), which also just feels wrong.
in the definition of LikeA, use std::remove_reference and std::const_cast to cast away references / constness, then check for the required functions. First, i don't know if this will always work for more complicated types, but even then, this now has the undesired effect that
static_assert(LikeA<const A>);
will be true, breaking (or at least bending) the semantics of the concept.
To summary and ensure you don't get me wrong, I would like to have a way that
does enforce const-correctness
does not use a second concept 'for the end-user'. With this I mean that it is of course okay to define auxiliary concepts or use some of the standard-library that help in defining above concept, but nothing that is actually required to use A and LikeA etc.
does not simply ignore non-const requirements for const types (as I mentioned, this would be compiler-wise okay, but semantically feels wrong)
does not define LikeA<const A> to be true
Ideally, there would just be a feature working like the already-mentioned
template<typename T>
concept LikeAHolder = requires (T t) {
{t.getA() } -> const LikeA; //invalid syntax
};
{[](const LikeA auto&){}( t.getA() )}
Note that a non-const& returning getA will pass this.
I made a lambda that does a concept check, then ensured t.getA() passes it.
void use (const LikeA auto &a)
This is shorthand for
template<LikeA A>
void use (const A&a)
and when called with a T const, it deduces A=T not A=T const. Why? Because it is "more correct" abstractly. Concretely, there are a pile of rules for how template argument type deduction works.

Are references helpful when operating in a constexpr/compile-time context only?

I am exploring the world of constexpr and have decided to create a class that should only be used in constexpr context and other compile-time constructs.
Usually, I take great care to provide all necessary overloads a class may need, for example:
template <typename T>
struct Thing
{
Thing(T value) : m_value(value) {}
T &value() & { return m_value; }
const T &value() const & { return m_value; }
T &&value() && { return std::move(m_value); }
private:
T m_value;
};
The set of overloads for Thing::value should take care of efficient access to the stored value, no unnecessary copies are made. If the Thing instance is a temporary, the stored value can even be moved out.
But what if Thing is only to be used as a constexpr type, are all these different overloads for Thing::value required or even helpful at all? Or would the following be equivalent:
template <typename T>
struct Thing
{
constexpr Thing(T value) : m_value(value) {}
constexpr T value() const;
private:
T m_value;
};
My question basically boils down to: are references helpful (more efficient) when operating in a constexpr/compile-time context only; or is passing everything by value equivalent?
My question basically boils down to: are references helpful (more efficient) when operating in a constexpr/compile-time context only; or is passing everything by value equivalent?
It's a matter of what's your actual problem and how you plan to solve it. In most of the cases (all of them?) you won't need to use references in such a context, I agree, but you can still use them if required.
Here as a minimal, working example:
const int i = 0;
template <typename T>
struct Thing {
constexpr Thing(const T &value) : m_value(value) {}
constexpr const T & value() const { return m_value; }
private:
const T & m_value;
};
int main() {
static_assert(Thing<int>{i}.value() == 0, "!");
}
See it up and running on wandbox.
So, are references helpful (more efficient) in this case? Well, it's not a matter of efficiency or whatever. To use references in such a context you have to have a good reason and the language sets a lot of limitations. They solve a specific problem, it's not your taste to decide to use references.
If your problem requires you to use references, they are there for you (and please, contact me - I'm just curious to know what's that problem!). Otherwise feel free to keep on with passing by value.

Can I define implicit conversion from std::function to std::shared_ptr<MyClass>?

I have a class that works as a predicate to select value from list.
class Predicate {
public:
// In this example, I am using QString as value type
// this is not what happens in actual code, where more complex data is being validated
virtual bool evaluate(const QString& val) const = 0;
};
Originally, I used lambda functions but this created lot of repetitive garbage code. So instead, I want to use predicate classes that use inheritance. For example:
class PredicateMaxLength: public RowPredicate {
public:
PredicateMaxLength(const int max) : maxLength(max) {}
virtual bool evaluate(const QString& val) const {return val.length()<maxLength;}
protected:
const int maxLength;
};
To allow inheritance do it's deed, pointers are given rather than values:
class SomeDataObject {
// Removes all values that satisfy the given predicate
int removeValues(const std::shared_ptr<Predicate> pred);
}
Now we are surely stil going to use lambdas in cases where code would not be repetitive (eg. some special case). For this purpose, PredicateLambda has been created:
typedef std::function<bool(const QString& val)> StdPredicateLambda;
class PredicateLambda: public Predicate {
public:
PredicateLambda(const StdPredicateLambda& lambda) : RowPredicate(), callback_(lambda) {}
virtual bool evaluate(const QString& val) const override {return callback_(val);}
protected:
const StdPredicateLambda callback_;
};
The nasty effect of this is that whenever lambda is used, it must be wrapped into PredicateLambda constructor:
myObject.deleteItems(std::make_shared<PredicateLambda>([]->bool{ ... lambda code ... }));
This is ugly. I have two options:
for every function that accepts predicate, have an overload that does the conversion seen above. This duplicates number of methods in header file
Have an implicit conversion from std::function<bool(const QString& val)> to std::shared_ptr<Predicate> which would execute this:
std::shared_ptr<Predicate> magicImplicitConversion(const StdPredicateLambda& lambdaFn) {
return std::make_shared<PredicateLambda>(lambdaFn);
}
I came here to ask whether the second option is possible. If it is, does it carry any risk?
If you don't want to use template to not expose code, you may use std::function:
class SomeDataObject {
// Removes all values that satisfy the given predicate
int removeValues(std::function<bool(const QString&)> pred);
};
and your predicate
class PredicateMaxLength {
public:
explicit PredicateMaxLength(int max) : maxLength(max) {}
bool operator ()(const QString& val) const {return val.length()<maxLength;}
protected:
int maxLength;
};
So you can use either
SomeDataObject someDataObject;
someDataObject.removeValues(PredicateMaxLength(42));
someDataObject.removeValues([](const QString& s) { return s.size() < 42; });
You want polymorphism, and you don't want to use template-style header lambdas. And you want to be able to have a few default cases.
The right answer is to throw out your Predicate class.
Use using Predicate = std::function<bool(const QString&)>;.
Next, note that your Predicate sub-types are basically factories (the constructor is a factory) for Predicates with some extra state.
For a std::function, such a factory is just a function returning a Predicate.
using Predicate = std::function<bool(const QString&)>;
Predicate PredicateMaxLength(int max) {
return [max](QString const& str){ return val.length()<max; }
}
where the body of PredicateMaxLength goes in a cpp file.
If you have an insanely complicated set of state for your Predicate-derived class, simply give it an operator() and store it within a std::function. (In the extremely rare case that you have some state you should store in a shared ptr, just store it in a shared ptr).
A std::function<Signature> is a regular type that is polymorphic. It uses a technique known as type erasure to be both a value and polymorphic, but really you can call it magic.
It is the right type to use when you are passing around an object whose only job is to be invoked with some set of arguments and return some value.
To directly answer your question, no, you cannot define a conversion operator between a std::function and a std::shared_ptr<yourtype> without making your program ill formed, no diagnostic required.
Even if you could, a std::function is not a lambda, and a lambda is not a std::function. So your conversion operator wouldn't work.

Const correctness with reference_wrapper

In various situations I have a collection (e.g. vector) of objects that needs to be processed by a number of functions. Some of the functions need to modify the objects while others don't. The objects' classes may inherit from an abstract base class. Hence, I have something like this:
class A
{
public:
virtual void foo() const = 0;
virtual void bar() = 0;
/* ... */
};
void process_1(std::vector<std::reference_wrapper<A>> const &vec);
void process_2(std::vector<std::reference_wrapper<A const>> const &vec);
Obviously (?) I can't pass the same vector of std::reference_wrapper<A>s to both process_1 and process_2. Solutions I've considered so far include:
Using a C-style cast or reinterpret_cast on a reference to vec
Writing my own reference wrapper that has T& get() and T const & get() const instead of T& get() const
Refactoring with e.g. methods that take a wrapper instead of the vector
Having copies of the vector with and without const
Not using const in reference_wrapper's argument
None of these seems very elegant. Is there something else I could do?
Range adapters.
A range adapter takes a range as input (a container is a range, as it has begin and end returning iterators), and returns a range with different properties.
You'd cast your reference wrappers to the const variant when you dereference the iterator.
boost has iterators that will do this for you (transform iterators), and tools to help write conforming iterators, but it can be done from scratch with some work.
A bit of extra work could even keep the typenames sane.
Even lacking elegance, I would make a reference wrapper:
#include <functional>
template <typename T>
class ReferenceWrapper
{
public:
ReferenceWrapper(T& ref)
: m_ref(ref)
{}
ReferenceWrapper(const std::reference_wrapper<T>& ref)
: m_ref(ref)
{}
const T& get() const noexcept { return m_ref.get(); }
T& get() noexcept { return m_ref.get(); }
operator const T& () const noexcept { return m_ref.get(); }
operator T& () noexcept { return m_ref.get(); }
private:
std::reference_wrapper<T> m_ref;
};
It is a tiny class modeling the original requirements.

Const and non-const access resolves to different overloads?

Let me say we have a simple programming task. But for the sake of clarity I start with few code samples.
First of all we written a some kind of data container class but for the purposes of task no matter what the class is. We just need it to behave const-correct.
class DataComponent {
public:
const std::string& getCaption() const {
return caption;
}
void setCaption(const std::string& s) {
caption = s;
}
private:
std::string caption;
};
Then let us assume we've got a generic class that behaves like facade over arbitrary incapsulated class instance. Say we overloaded member access operator (->).
template <typename T> class Component {
public:
Component() { instance = new T(); }
...
const T* operator-> () const {
return instance;
}
T* operator-> () {
// but there might be additional magic
return instance;
}
private:
T *instance;
};
At this point I should say how I want this to work:
if we're calling non-const member functions of underlying class through member access operator (component->setCaption("foo")) compilier treats non-const T* operator-> () as the best choice.
otherwise if we are trying to call const member functions of underlying class same way (component->getCaption()) compiliers selects const T* operator-> () const on the other hand.
This code sample above won't work this way so I'm curious about possibility to give compiler a behavior like that I have mentioned. Any propositions.
EDIT: Let our member access operator overloaded this way:
const T* operator-> () const { return instance; }
T* operator-> () {
cout << "something going change" << endl;
return instance;
}
And let us have a variable Component<DataComponent> c somewhere. Then on the call to c->getCaption() stdout should remain silent but on the call to c->setCaption("foo") stdout should warn us that something is going to change. VS 2010 compilier makes stdout warn us on each of these calls.
I understand that such semantics suppose that c behaves as const and non-const at the same time. But curiousity is still in my mind.
Whether a const or non-const member is invoked is determined purely by the constness of the object on which it is invoked, not by some subsequent operation. That determination is made before any consideration of the particular method you're invoking in DataComponent. You could still hack up the required functionality less directly using proxy object around DataComponent, with both const and non-const forwarding getCaption()s.
EDIT: details as requested (off the top of my head). You'll need to forward declare some of this stuff - I didn't bother as it makes it even more confusing. Do chip in with any concerns / feedback. Note that this basically assumes you can't / don't want to modify Component for some reason, but it's not a generic templated solution that can simply be wrapped around any arbitrary type - it's very heavily coupled and has a high maintenance burden.
// know they can't call a non-const operation on T, so this is ok...
const T* Component::operator->() const { return instance; }
// they might invoke a non-const operation on T, so...
DataComponent::Proxy Component::operator->() { return DataComponent.getProxy(*this); }
in class DataComponent:
struct Proxy
{
Component& c_;
DataComponent& d_;
Proxy(Component& c, DataComponent& d) : c_(c), d_(d) { }
const std::string& get_caption() const { return d_.get_caption(); }
void set_caption(const std::string& s)
{
c_.on_pre_mutator(d_);
d_.set_caption(s);
c_.on_post_mutator(d_);
}
};
then
DataComponent::Proxy DataComponent::getProxy(Component& c) { return Proxy(c, *this); }
So, this means somewhere you have to hand-code forwarding functions. It's a pain, but if you're doing this for debugging or testing it's not unreasonable. If you're doing this so you can add a lock or something, then there are probably better alternatives.