I have to create a template function that searches an element in a map variable. If the element exists, the function must return it. Otherwise it must return NULL.
template <class K, class E> E dictionary<K,E>::research(K key) {
// map<K,E> elements;
if(elements.find(key) != elements.end()) {
return elements.find(key)->second;
} else {
return NULL;
}
Since the return type is E, returning NULL gives me always an error. How can I make this work? Or I have to structure my function differently?
This is a school homework assignment and I must return NULL, no alternatives. I'd personally do differently if I could.
The design of this function is incorrect. It is perfectly possible that NULL is simply incompatible with the type E. For instance, suppose that E is a struct, or a std::string and so on.
This is a school homework assignment and I must return NULL, no alternatives.
Either your homework assignment is incorrect, or you have misunderstood its requirements. It is possible that you are expected to return a pointer to E?
Instead of returning pointers, you could consider returning something like boost::optional, i.e. a type that is either set to contain a valid object or in an invalid state. That mimics a pointer in some way, but is more explicit
The following is just to show the principle, the implementation can for sure be optimized.
template<typename T> class Optional {
public:
Optional(E e):
isValid(true),
mValue(e)
{}
Optional(): isValid(false), mValue() {}
bool isDefined() const {return isValid;}
E getOrElse(E const& other) const {return (isValid) ? (mValue) : (other);}
E get(E const {return mValue;}
private:
bool isValid;
T mValue;
};
Related
I just learned about the std::optional feature in c++ 17 along with a few other very useful features...
but there is a few things that I don't understand about std::optional that I would like someone to explain them to me:
first of all as far as I know in std::optional the return value can either be the specified type or it can be nothing like this :
std::optional<std::string> getName()
{
if(person.hasName())
{
return person.name;
}
else
{
return {};
}
}
how does return {} returns nothing ? like for example if I was to make a similar class that return either the specified value or nothing, how do I make my own class so return {} is valid ? I'm I misunderstanding something here ?
my second question is that when you want to check the return value you can either do :
int main()
{
std::optional<std::string> name = getName();
if(name.has_value()) // check if the name is valid using the has_value function
{
...
}
}
or i can also do :
int main()
{
std::optional<std::string> name = getName();
if(name) // check if the name is valid only using the variable name ???
{
...
}
}
I'm really confused about this how could a variable name return a boolean ? not like the constructor of an object can return anything, so how is this possible ?
again let's say I want to make my own class that is kind of similar to std::optional how do I make it so an instance of my class can be used as a boolean ?
I would really appreciate answers that adress my questions and not something related to when to use std::optional or why I shouldn't make my own class that does the same thing etc...
thanks!
return {};
will simply call the default constructor of the class.
By giving the class a conversion operator to bool it can be implicitly converted to a bool when needed.
It would look something along the lines of
template <typename T>
class optional {
public:
optional() {}
optional(T t) : has_value(true), value(std::move(t)) {}
operator bool() {
return has_value;
}
private:
bool has_value = false;
T value;
}
Very simplified, missing assignement operators and more.
how do I make my own class so return {} is valid ?
By making the class default constructible. Exactly how to do that depends on the class. In cases where the class is implicitly default constructible you need to do nothing, while in other cases you may need to explicitly declare the constructor. Like this for example: ClassName() = default;.
how could a variable name return a boolean
Think about how this variable name "returns a boolean":
int x = 42;
if (x)
;
Or how this variable name "returns a std::string_view":
const char* str = "example";
std::string__view sv = str;
This is called a conversion from one type to another. That is what happens in if(name).
how do I make it so an instance of my class can be used as a boolean ?
By providing a conversion operator.
Assume we need a function that returns something. But that something can be not found. I see options:
1. T find(bool &ok); //return default T value if not found
We can make a struct:
template <typename T>
class CheckableValue
{
public:
CheckableValue(),
_hasValue(false)
{
}
CheckableValue(const T &t):
_value(t),
_hasValue(true)
{
}
inline bool hasValue() const {return _hasValue}
const T &value() const
{
assert(hasValue());
return _value;
}
private:
T _value;
bool _hasValue;
};
and make the function:
2. CheckableValue<T> find();
Or we can use:
3.boost::tuple<bool, T> find()
What do you think is preferable ?
I prefer:
4. boost::optional<T> find();
The problem with the tuple is that the T part is invalid when the bool part is false; this behaviour is not enforced by the tuple. Your CheckableValue class is the same remedy as boost::optional for the same problem.
returns something. But that something can be not found.
Are you actually planning to return a copy, or some kind of reference for the thing? "not found" implies that the function works by "finding" a pre-existing value in a data structure somewhere.
In that case, the simple solution is to return a pointer to the existing value, using NULL for not-found.
I'd like a pointer wrapper class that acts just like a raw pointer but also saves a special integer along with the pointer (Type's index in the array it came from)
I managed to have it behave mostly like a pointer. I am aware that the pointer comparison solution might not be optimal but that's not my main problem.
I want the wrapper to be constructed with 2 parameters(pointer,indexToArr), unless the pointer is NULL - then I don't care about indexToArr.
The problem I'm trying to solve is how to allow returning NULL just like a normal pointer allows.
current solution uses an ASSERT. But I want something that works in compile-time. something in the spirit of a specialized template method - allowing only NULL as its argument.
Current version:
class PtrWrapper
{
public:
PtrWrapper(Type* ptr, int indToArr)
: m_ptr(ptr), m_indexToArr(indToArr){}
//allow returning NULL, only NULL
PtrWrapper(Type* ptr) : m_ptr(NULL), m_indexToArr(-1) {ASSERT(ptr == NULL);}
Type* operator->() const {return m_ptr;}
Type& operator*() const {return *m_ptr;}
int IndexToArr() const {return m_indexToArr;}
//for pointer comparison
operator Type*() const {return m_ptr;}
private:
Type* m_ptr;
int m_indexToArr;
};
Any ideas, suggestions?
Thanks,
Leo
template<typename Type>
class PtrWrapper
{
typedef struct { } NotType;
public:
Ptr() { }
Ptr(const NotType* nullPtr) { }
Ptr(Type* p, int index) { }
};
You can exploit the fact that literal NULL / 0 can be auto-cast to any pointer type. Create a type that is NOT T, and a constructor which takes a single pointer to that type which nobody will ever use. Now you can handle PtrWrapper<T> x(NULL); explicitly.
Of course as others have said, this is only going to work if NULL is known at compile-time.
Simply make a default constructor with no arguments that initializes your pointer to NULL, but make sure to have some checks in your operator* and operator-> for a NULL pointer.
Do the following:
PtrWrapper(Type* ptr) : m_ptr(ptr), m_indexToArr(0) {ASSERT(ptr != NULL);}
PtrWrapper() : m_ptr(NULL), m_indexToArr(-1) {ASSERT(ptr == NULL);}
My situation is the following:
I have a template wrapper that handles the situation of values and object being nullable without having to manually handle pointer or even new. This basically boils down to this:
struct null_t
{
// just a dummy
};
static const null_t null;
template<class T> class nullable
{
public:
nullable()
: _t(new T())
{}
nullable(const nullable<T>& source)
: _t(source == null ? 0 : new T(*source._t))
{}
nullable(const null_t& null)
: _t(0)
{}
nullable(const T& t)
: _t(new T(t))
{}
~nullable()
{
delete _t;
}
/* comparison and assignment operators */
const T& operator*() const
{
assert(_t != 0);
return *_t;
}
operator T&()
{
assert(_t != 0);
return *_t;
}
operator const T&() const
{
assert(_t != 0);
return *_t;
}
private:
T* _t;
};
Now with the comparison operators I can check against the null_t dummy in order to see whether it is set to null before actually trying to retrieve the value or pass it into a function that requires that value and would do the automatic conversion.
This class has served me well for quite some time, until I stumbled about an issue. I have a data class containing some structs which will all be outputted to a file (in this case XML).
So I have functions like these
xml_iterator Add(xml_iterator parent, const char* name,
const MyDataStruct1& value);
xml_iterator Add(xml_iterator parent, const char* name,
const MyDataStruct2& value);
which each fill an XML-DOM with the proper data. This also works correctly.
Now, however, some of these structs are optional, which in code would be declared as a
nullable<MyDataStruct3> SomeOptionalData;
And to handle this case, I made a template overload:
template<class T>
xml_iterator Add(xml_iterator parent, const char* name,
const nullable<T>& value)
{
if (value != null) return Add(parent, name, *value);
else return parent;
}
In my unit tests the compiler, as expected, always preferred to choose this template function whereever a value or structure is wrapped in a nullable<T>.
If however I use the aforementioned data class (which is exported in its own DLL), for some reason the very first time that last template function should be called, instead an automatic conversion from nullable<T> to the respective type T is done, completely bypassing the function meant to handle this case. As I've said above - all unit tests went 100% fine, both the tests and the executable calling the code are being built by MSVC 2005 in debug mode - the issue can definitely not be attributed to compiler differences.
Update: To clarify - the overloaded Add functions are not exported and only used internally within the DLL. In other words, the external program which encounters this issue does not even include the head with the template overloaded function.
The compiler will select primarily an exact match before it finds a templated version but will pick a templated "exact match" over another function that fits, eg, one that uses a base class of your type.
Implicit conversions are dangerous and often bite you. It could simply be that way you are including your headers or the namespaces you are using.
I would do the following:
Make your constructors of Nullable all explicit. You do this with any constructors that take exactly one parameter, or can be called with one (even if there are more that have default values).
template<class T> class nullable
{
public:
nullable()
: _t(new T())
{}
explicit nullable(const nullable<T>& source)
: _t(source == null ? 0 : new T(*source._t))
{}
explicit nullable(const null_t& null)
: _t(0)
{}
explicit nullable(const T& t)
: _t(new T(t))
{}
// rest
};
Replace the operator T& conversions with named functions. Use ref() for the non-const and cref() for the const.
I would also complete the class with
assignment operator (needed for rule of 3)
operator-> two overloads as you are propagating the constness.
If you plan to use this for C++0x also the r-value copy and assign, which is useful in this case.
By the way, you do know your deep copy won't work with base classes as they will slice.
Well, since no real answer was found so far, I've made a workaround. Basically, I put the aforementioned Add functions in a seperate detail namespace, and added two template wrapper functions:
template<class T>
xml_iterator Add(xml_iterator parent, const char* name,
const T& value)
{
return detail::Add(parent, name, value);
}
template<class T>
xml_iterator Add(xml_iterator parent, const char* name,
const nullable<T>& value)
{
return value != null ? detail::Add(parent, name, *value) : parent;
}
I found this to always properly resolve to the correct one of those two functions, and the function for the actual contained type will be chosen in a seperate step inside these, as you can see.
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;
}
}