This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Elegant solution to duplicate, const and non-const, getters?
Say I have a c++ class with a memberfunction which is overloaded for const, like this:
Type* DoSomething();
const Type* DoSomething() const;
If this is a larger, more complex member, how does one prevent having to write the same code twice ? Can't call any non-const functions from the const one. And calling the const version from the non-const one results in a const pointer wich has to be cast to non-const (wich smells a bit imo).
You can delegate to a template static member function, as in:
class Widget
{
Type member;
template<typename Result, typename T>
static Result DoSomethingImpl(T This)
{
// all the complexity sits here, calculating offsets into an array, etc
return &This->member;
}
public:
Type* DoSomething() { return DoSomethingImpl<Type*>(this); }
const Type* DoSomething() const { return DoSomethingImpl<const Type*>(this); }
};
In C++11, you can even get rid of the non-inferred template argument, with:
static auto DoSomethingImpl(T This) -> decltype(This->member)
You did it once, and to do it second time with a const attribute on the class, you can use const_cast:
class Foo
{
Type* DoSomething()
{
// Lots of stuff
}
const Type* DoSomething() const
{
return const_cast<Foo*>(this)->DoSomething();
}
}
Use the template method pattern to extract the common code from them. Eg.
inline const T* prev(size_t i) const
{
return &FBuffer[ AdjustIndex(i) ];
}
inline T* prev(size_t i)
{
return &FBuffer[ AdjustIndex(i) ];
}
inline size_t AdjustIndex( size_t i ) const
{
return Math::ModInt( static_cast<int>( FHead ) - 1 - i, static_cast<int>( FBuffer.size() ) );
}
This technique can be applied in many cases (but not all of them, i.e. if the behavior differs significantly).
Related
This question already has answers here:
is it possible to make function that will accept multiple data types for given argument?
(4 answers)
Closed 5 years ago.
I have some classes, named c1, c2, ... that all have a function in common named get_value().
now I want to write a function like this:
int foo(any_class_type obj){ return process(obj.get_value() ); }
how can I do this?
Writing a templated function might well do what you want:
template<typename any_class_type>
int foo(any_class_type obj){ return process(obj.get_value); }
You can either use a function template
template<typename T>
int foo(T const&obj)
{
return obj.getValue();
}
or use polymorphism:
struct C
{
virtual int getValue() const = 0;
};
struct C1 : C
{
int getValue() const override;
};
struct C2 : C
{
int getValue() const override;
};
int foo(C const&obj)
{
return obj.getValue();
}
or overload your function explicitly for the (some of the) types
int foo(C1 const&obj) { return obj.getValue(); }
int foo(C2 const&obj) { return obj.getValue(); }
or combine these approaches (when the best match will be picked).
A template allows unrelated object types and tends to generate more efficient code than polymorphic functions, but is header-only and also may result in cumbersome compiler error messages should you call it with an argument that does not have a fitting member getValue.
This question already has answers here:
How to pass objects to functions in C++?
(8 answers)
Closed 6 years ago.
//Array-based Class ‘LinearList’
template <class T>
class LinearList
{
public:
LinearList(int MaxListSize = 10);
~LinearList() { delete [] element; }
bool isEmpty() const { return length == 0; } //1
int Length() const { return length; } //2
bool Find(int k, T& x) const; //3
int Search(const T& x) const; //4
LinearList<T>& Delete(int k, T& x);
LinearList<T>& Insert(int k, const T& x); //5
void Output(ostream& out) const; //6
private:
int length;
int MaxSize;
T *element;
};
A const at the end of a method declaration (ie void Foo() const) means that the method does not alter the state of the object.
When a parameter is flagged as const it means the method cannot change the parameter. For example, void DoSomething(const T &t) declares that DoSomething can only call methods declared as const on the object.
These lines simply mean that if you instantiate the class, you cannot use these methods unless your class is a const instance or - more precisely - the reference/pointer/access to your object is const. So, let's say, you have some function where such a list is passed:
void readSomethingFromList(const LinearList<int>& list)
{
list.Insert(10, 20); // not working, compile-time error
int n = list.Length(); // this is fine
}
So, const marks a method as readonly and if the object is not readonly, then it cannot be used and will not compile. This assures that a function like readSomethingFromList will really not change the object in any way. This makes your code less prone to errors and all in all more stable. So, whenever you have methods that will not change the object, you should mark them const.
Since this is basic knowledge, you should probably read a book about C++ thoroughly. Otherwise, you will also miss other important language concepts of C++ and might even apply them in a wrong way, which can be fatal. As this is so basic, you probably also get all those downvotes.
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.
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.
I have another question related to the safe bool idiom:
typedef void (Testable::*bool_type)() const; // const necessary?
void this_type_does_not_support_comparisons() const {} // const necessary?
operator bool_type() const
{
return ok_ ? &Testable::this_type_does_not_support_comparisons : 0;
}
How come the bool_type (the typedef) and this_type_does_not_support_comparisons are const?
Nobody is supposed to actually call the member function through the return pointer anyway, right?
Is const necessary here? Would operator bool_type (the member function) violate const-correctness otherwise?
The "safe bool idiom" is the technical answer to the question "i want a vehicle that is both sports car and tractor, and maybe a boat". The practical answer is not the technical answer…
That said, the problem it solves is just to give a result that is convertible to bool but not to much of anything else (otherwise an instance of the class could be passed as actual argument where e.g. the formal argument was int, say). A data pointer could be convertible to void*. A function pointer isn't, at least formally within the C++ standard (Posix is something else, practice also).
Using a member function pointer protects against accidentally calling the function, given the pointer from the safe bool operator. The const constricts it a bit, but if fate has put someone on the path of making maximum number of silly mistakes, that person might still manage to call the do-nothing function. Instead of the const I think I would just let it have an argument of a private type, where other code cannot provide such an argument, and then it doesn't have to be a silly member function type anymore.
Can look like this:
#include <stdio.h>
class Foo
{
private:
enum PrivateArg {};
typedef void (*SafeBool)( PrivateArg );
static void safeTrue( PrivateArg ) {}
bool state_;
public:
Foo( bool state ): state_( state ) {}
operator SafeBool () const
{ return (state_? &safeTrue : 0); }
};
int main()
{
if( Foo( true ) ) { printf( "true\n" ); }
if( Foo( false ) ) { printf( "false\n" ); } // No output.
//int const x1 = Foo( false ); // No compilado!
//void* const x2 = Foo( false ); // No compilado!
}
Of course, the practical answer is instead something like this:
#include <stdio.h>
class Foo
{
private:
bool isEmpty_;
public:
Foo( bool asInitiallyEmpty )
: isEmpty_( asInitiallyEmpty )
{}
bool isEmpty() const { return isEmpty_; }
};
int main()
{
if( Foo( true ).isEmpty() ) { printf( "true\n" ); }
if( Foo( false ).isEmpty() ) { printf( "false\n" ); } // No output.
//bool const x0 = Foo( false ); // No compilado!
//int const x1 = Foo( false ); // No compilado!
//void* const x2 = Foo( false ); // No compilado!
}
Summary wrt. questions asked:
How come the bool_type (the typedef) and this_type_does_not_support_comparisons are const?
Somebody didn't quite understand what they coded. Or maybe they intended to restrict the ability to call, a little. But then, pretty futile measure.
Nobody is supposed to actually call the member function through the return pointer anyway, right?
Right.
Is const necessary here?
No.
Would operator bool_type (the member function) violate const-correctness otherwise?
No.
Cheers & hth.,
8.3.5/ A cv-qualifier-seq shall only be part of the function type for
a nonstatic member function, the function type to which a pointer to
member refers, or the top-level function type of a function typedef
declaration. The effect of a cv-qualifier-seq in a function declarator
is not the same as adding cv-qualification on top of the function
type, i.e., it does not create a cv-qualified function type.
If I read correctly, you can return a pointer to non const member in a const member function. You just won't be able to call it with a non const object.
A way to forbid the calling is:
private:
struct private_
{
void this_type_does_not_support_comparisons() {}
};
public:
typedef void (private_::*bool_type)() const;
operator bool_type() const
{
return ok_ ? &private_::this_type_does_not_support_comparisons : 0;
}
Pointer to member functions can still be compared for equality. You have to write an operator== and operator!= for Testable::bool_type types which trigger an error. Easier to do with the CRTP form of the safe bool idiom since those operators become templates and thus can have an erroneous body.
Example:
template <typename T>
class safe_bool_concept
{
// Implementation detail of safe bool
protected:
~safe_bool_concept() {}
public:
operator safe_bool() const
{
return static_cast<const T*>(this)->is_null() ? ...;
}
};
struct Foo : safe_bool_concept<Foo>
{
...
private:
friend class safe_bool_concept<Foo>;
bool is_null() const { ... }
};
then you can do (do the same with !=):
template <typename T>
void operator==(const safe_bool_concept<T>& x, const safe_bool_concept<T>&)
{
x.some_private_member(); // invalid, but won't be generated
// unless safe_bool classes are compared
}
This means that the safe bool idiom should be implemented via CRTP if you want to forbid comparisons. Comparisons to zero will still work however.
If you go the non-member function route, you'll have to provide <, >, <= and >= too.