Inherit Initialization Syntax from std::set or std::map - c++

The standard library neglects to implement basic operations for std::set and std::map like
set<T> set<T>::getUnion(set<T> other)
and
bool map<K,V>::contains(K key)
I know there are verbose and/or indirect workarounds for these methods but if I want my code to be maximally readable and expressive, I'm going to have to inherit from the STL, write my own Set and Map classes, and implement them myself. And yes, I'm aware of the sermonizing against doing this but the fact is the STL is incomplete.
I've done this but now I can't initialize my new classes using, e.g.,
Set<int> s = {1,2,3,4};
How do I inherit these initializers from the std classes?

Despite the fact that publically inheriting from standard library containers is considered to be a bad idea, you can "inherit" the constructors:
template <typename T>
struct Set : std::set<T>
{
using std::set<T>::set; // "inherit" the constructors.
};
then
Set<int> s{1,6,4,3,3,9};
Note that a better approach might be to implement functions:
template <typename C>
bool contains(const C& container, const typename C::key_type& key)
{
return container.count(key);
}
and similarly for the union of sets.

For gcc 4.7.x, you have to call the initializer_list constructor for the set or map:
template <typename T>
class Set : public set<T> {
public:
Set(){
set<T>::set();
}
Set(initializer_list<T> iList) {
set<T>::set(iList);
}
};
Allowing
Set<int> s = {1,2,3,4};
But after much trial and error, I can't find a way to do this for std::map.
Also, it disables all the other constructors, requiring me to reimplement them, a task I'm not up to yet, so I'm just giving up on initializer lists for now. Anyone is welcome to submit an answer that reimplements all the constructors as Set and I'll choose it as the answer.

Related

Generic operator== for non-pod objects

While doing some unit tests I want to be able to compare some pretty simple structs (they contain only public data members). I could write a operator== for all of them separately but it would be cumbersome and repetitive. So I decided to try to do this in a generic way. Yet there is a problem - some of them are not POD as some of their fields have non-POD type, let's say a std::list for an example.
struct NonPod {
std::list<int> lst;
};
struct NonPod2 {
std::list<NonPod> lst;
};
template<class T>
bool operator==(const T& lhs, const T& rhs) {
//what should I put here to make it work safely
//to compare NonPod with other NonPod
//ant NonPod2 with other NonPod2
}
AFAIK, to compare POD safely I could just use std::memcmp and it would be all fine. Is it possible to do generic operator== for non-POD types as well? If so, how?
Sadly, there is no way to do this in C++17 (or earlier). C++20 will allow you to add:
auto operator<=>(const class_name&) const = default;
to each class. This will give you all the comparison operators defined in the obvious way.
If the classes are being created by a code generator, then adding a comparison function should be easy.

(unordered_)set and inheritance, good practice? [duplicate]

I have a class that adapts std::vector to model a container of domain-specific objects. I want to expose most of the std::vector API to the user, so that they may use familiar methods (size, clear, at, etc...) and standard algorithms on the container. This seems to be a reoccurring pattern for me in my designs:
class MyContainer : public std::vector<MyObject>
{
public:
// Redeclare all container traits: value_type, iterator, etc...
// Domain-specific constructors
// (more useful to the user than std::vector ones...)
// Add a few domain-specific helper methods...
// Perhaps modify or hide a few methods (domain-related)
};
I'm aware of the practice of preferring composition to inheritance when reusing a class for implementation -- but there's gotta be a limit! If I were to delegate everything to std::vector, there would be (by my count) 32 forwarding functions!
So my questions are... Is it really so bad to inherit implementation in such cases? What are the risks? Is there a safer way I can implement this without so much typing? Am I a heretic for using implementation inheritance? :)
Edit:
What about making it clear that the user should not use MyContainer via a std::vector<> pointer:
// non_api_header_file.h
namespace detail
{
typedef std::vector<MyObject> MyObjectBase;
}
// api_header_file.h
class MyContainer : public detail::MyObjectBase
{
// ...
};
The boost libraries seem to do this stuff all the time.
Edit 2:
One of the suggestions was to use free functions. I'll show it here as pseudo-code:
typedef std::vector<MyObject> MyCollection;
void specialCollectionInitializer(MyCollection& c, arguments...);
result specialCollectionFunction(const MyCollection& c);
etc...
A more OO way of doing it:
typedef std::vector<MyObject> MyCollection;
class MyCollectionWrapper
{
public:
// Constructor
MyCollectionWrapper(arguments...) {construct coll_}
// Access collection directly
MyCollection& collection() {return coll_;}
const MyCollection& collection() const {return coll_;}
// Special domain-related methods
result mySpecialMethod(arguments...);
private:
MyCollection coll_;
// Other domain-specific member variables used
// in conjunction with the collection.
}
The risk is deallocating through a pointer to the base class (delete, delete[], and potentially other deallocation methods). Since these classes (deque, map, string, etc.) don't have virtual dtors, it's impossible to clean them up properly with only a pointer to those classes:
struct BadExample : vector<int> {};
int main() {
vector<int>* p = new BadExample();
delete p; // this is Undefined Behavior
return 0;
}
That said, if you're willing to make sure you never accidentally do this, there's little major drawback to inheriting them—but in some cases that's a big if. Other drawbacks include clashing with implementation specifics and extensions (some of which may not use reserved identifiers) and dealing with bloated interfaces (string in particular). However, inheritance is intended in some cases, as container adapters like stack have a protected member c (the underlying container they adapt), and it's almost only accessible from a derived class instance.
Instead of either inheritance or composition, consider writing free functions which take either an iterator pair or a container reference, and operate on that. Practically all of <algorithm> is an example of this; and make_heap, pop_heap, and push_heap, in particular, are an example of using free functions instead of a domain-specific container.
So, use the container classes for your data types, and still call the free functions for your domain-specific logic. But you can still achieve some modularity using a typedef, which allows you to both simplify declaring them and provides a single point if part of them needs to change:
typedef std::deque<int, MyAllocator> Example;
// ...
Example c (42);
example_algorithm(c);
example_algorithm2(c.begin() + 5, c.end() - 5);
Example::iterator i; // nested types are especially easier
Notice the value_type and allocator can change without affecting later code using the typedef, and even the container can change from a deque to a vector.
You can combine private inheritance and the 'using' keyword to work around most of the problems mentioned above: Private inheritance is 'is-implemented-in-terms-of' and as it is private you cannot hold a pointer to the base class
#include <string>
#include <iostream>
class MyString : private std::string
{
public:
MyString(std::string s) : std::string(s) {}
using std::string::size;
std::string fooMe(){ return std::string("Foo: ") + *this; }
};
int main()
{
MyString s("Hi");
std::cout << "MyString.size(): " << s.size() << std::endl;
std::cout << "MyString.fooMe(): " << s.fooMe() << std::endl;
}
As everyone has already stated, STL containers do not have virtual destructors so inheriting from them is unsafe at best. I've always considered generic programming with templates as a different style of OO - one without inheritance. The algorithms define the interface that they require. It is as close to Duck Typing as you can get in a static language.
Anyway, I do have something to add to the discussion. The way that I have created my own template specializations previously is to define classes like the following to use as base classes.
template <typename Container>
class readonly_container_facade {
public:
typedef typename Container::size_type size_type;
typedef typename Container::const_iterator const_iterator;
virtual ~readonly_container_facade() {}
inline bool empty() const { return container.empty(); }
inline const_iterator begin() const { return container.begin(); }
inline const_iterator end() const { return container.end(); }
inline size_type size() const { return container.size(); }
protected: // hide to force inherited usage only
readonly_container_facade() {}
protected: // hide assignment by default
readonly_container_facade(readonly_container_facade const& other):
: container(other.container) {}
readonly_container_facade& operator=(readonly_container_facade& other) {
container = other.container;
return *this;
}
protected:
Container container;
};
template <typename Container>
class writable_container_facade: public readable_container_facade<Container> {
public:
typedef typename Container::iterator iterator;
writable_container_facade(writable_container_facade& other)
readonly_container_facade(other) {}
virtual ~writable_container_facade() {}
inline iterator begin() { return container.begin(); }
inline iterator end() { return container.end(); }
writable_container_facade& operator=(writable_container_facade& other) {
readable_container_facade<Container>::operator=(other);
return *this;
}
};
These classes expose the same interface as an STL container. I did like the effect of separating the modifying and non-modifying operations into distinct base classes. This has a really nice effect on const-correctness. The one downside is that you have to extend the interface if you want to use these with associative containers. I haven't run into the need though.
In this case, inheriting is a bad idea: the STL containers do not have virtual destructors so you might run into memory leaks (plus, it's an indication that STL containers are not meant to be inherited in the first place).
If you just need to add some functionality, you can declare it in global methods, or a lightweight class with a container member pointer/reference. This off course doesn't allow you to hide methods: if that is really what you are after, then there's no other option then redeclaring the entire implementation.
Virtual dtors aside, the decision to inherit versus contain should be a design decision based the class you are creating. You should never inherit container functionality just because its easier than containing a container and adding a few add and remove functions that seem like simplistic wrappers unless you can definitively say that the class you are creating is a kind-of the container. For instance, a classroom class will often contain student objects, but a classroom isn't a kind of list of students for most purposes, so you shouldn't be inheriting from list.
It is easier to do:
typedef std::vector<MyObject> MyContainer;
The forwarding methods will be inlined away, anyhow. You will not get better performance this way. In fact, you will likely get worse performance.
Always consider composition over inheritance.
Consider the case:
class __declspec(dllexport) Foo :
public std::multimap<std::string, std::string> {};
Then symbols of std::multimap will be exported into your dll, which may cause compilation error "std::multimap already defined".

How to add an Initializer List constructor to STL vector

So what I want to do is extend the existing vector class in my program to allow me to say this,
vector<string>* vec = new vector<string>(){"Value1","Value2"};
or
vector<string>* vec = new vector<string>({"Value1","Value2"});
or
vector<string> vec = {"Value1","Value2"};
I know I can accomplish something like this but doing this,
string temp[] = {"Value1","Value2"};
vector<string> vec(temp, temp+ sizeof(temp) / sizeof( temp[0] ) );
This uses the vectors iterator constructor but can't I remove the extra line?
I know in C# you can add whatever you want to existing things by using the partial key word like this,
public partial class ClassName
{
ClassName(Stuff stuff)
{
}
void AmazingNewMethod()
{
}
}
Does C++ have a nifty trick like this somewhere?
Do I have to inherit vector and build a customVector that has a constructor that behind the scenes does the iterator constructor thing?
Maybe wrap those lines in a static Helper Function call that sets it by Reference and add it to a toolbox class somewhere?
I feel like lots of programmers have hit this problem. Are there any elegant solutions out there?
Thanks.
Edit: fixed the title to mention this is an Initializer List constructor.
In C++11 there would be initializer lists to suite this approach. As you're mentioning .NET I now assume that you're using MS Visual Studio. Microsoft does NOT implement initializer lists, therefore the easiest way to accomplish something like that would be a function that returns the vector with all the elements added.
On the partial thing: C++ does not offer a feature in the same vein as .NET's partial classes.
The C++ 2011 way is to accept an std::initializer_list<T> as a constructor argument:
#include <initializer_list>
template <typename T>
class foo {
T *d_array;
public:
foo(std::initializer_list<T> list)
: d_array(new T[list.size()]) {
std::copy(list.begin(), list.end(), this->d_array);
}
foo(foo const&);
foo& operator= (foo const&);
~foo() { delete[] this->d_array; }
};
The above clearly only concentrates on how use an std::initializer_list<T>. To actually do the allocation internally you'd allocate raw memory and construct the object in-place. However, this wasn't what the question is about.
With respect to adding this support to std::vector<T>: you don't have to! In C++ 2011 std::vector<T> can be initialized with an std::initializer_list<T>. In C++ 2003 you can't do this. The best you could do is to support construction from an array, using a constructor looking something like this:
template <typename T>
template <typename S, int Size>
foo<T>::foo(S const (&array)[Size])
d_array(new T[Size]) {
std::copy(array, array + Size, d_array);
};
However, there is no way to extend an existing without changing its type. To avoid reimplementing most of the members you could publically inherit from the type you want to extend and add all required constructors (these are not inherited; in C++ 2011 you could inherit the existing constructors but then, with C++ 2011 you wouldn't need to do any of this anyway).
An alternative you might want to use with C++ 2003 is to create a factor function taking a built-in array, i.e. something like this:
template <typename T, typename S, int Size>
std::vector<T>
make_vector(S const (&array)[Size]) {
return std::vector<T>(array, array + Size);
}
char const* init[] = { "Hello", "World" };
std::vector<std::string> value = make_vector<std::string>(init);

errors porting C++ templates from GCC to Visual C++

The following compiles in GCC:
cvec.hpp:
template <class T>
class cvec : public deque<T>
{
class deque<T>::iterator Find(T);
};
cvec.cpp:
template <class T>
class deque<T>::iterator cvec<T>::Find(T element)
{
}
In Visual C++, get:
error C2242 "typedef name cannot follow class/struct/union.
I changed "class" in the header file to "typename", but receive error C3860 - template argument list must list parameters in the order used in the template param list. There is only one parameter in this case, T. Unless the compiler is confused about Find(T element)?
What is this supposed to mean in the header:
class deque<T>::iterator Find(T);
You are not declaring a class. The typename keyword would be valid here, but class makes no sense.
And the same is true in the .cpp file:
template <class T>
typename deque<T>::iterator cvec<T>::Find(T element)
is correct, class isn't.
Apart from this, it really looks like what you're trying to do is a horrible idea. std::deque already has a find function. It works. It is correct. It is efficient. There is no need to reinvent it.
The standard library containers are also not designed to be derived from. They don't have virtual destructors.
All you're achieving (apart from the compile errors) is that you're going to end up with a buggy, less efficient container class that'll confuse other C++ programmers because it doesn't use the idiomatic interface.
This should really be a comment, but I'm making it an answer so that I can format it for readability.
#jalf and #dvl -- As #dvl said above, none of the std containers have virtual destructors. Why does that matter?
Let's say you derive a class "X" from from std::deque.
class X : public std::deque<int>
{
// whatever ...
};
Let's now say that you have an "X" object, pointed to by a base pointer.
std::deque<int> *p = new X;
and you delete it
delete p;
The destructor for the derived class X will not be called, which can lead to lots of problems.
Your options:
1. Don't derive from std containers. Make them data members and write wrappers to expose the functionality.
2. Only derive from std containers if the derived class has no destructor and no data members with destructors.
3. If you derive from a std container, never refer to it by a base pointer.
After you create a class, it is sometimes hard to know how the class might be used in the future. For that reason, many developers stick strictly to option "1". Personally I permit deriving from a std container as long as it is well documented and used with care.
This works for me in 2010:
#include <deque>
template <class T>
class cvec : public std::deque<T>
{
public:
typedef typename std::deque<T>::iterator iterator;
iterator Find(T element);
};
template <class T>
typename cvec<T>::iterator cvec<T>::Find(T element)
{
return std::deque<T>::iterator();
}
using namespace std;
int main()
{
cvec<int> c;
c.Find(1);
return 0;
}

Is it okay to inherit implementation from STL containers, rather than delegate?

I have a class that adapts std::vector to model a container of domain-specific objects. I want to expose most of the std::vector API to the user, so that they may use familiar methods (size, clear, at, etc...) and standard algorithms on the container. This seems to be a reoccurring pattern for me in my designs:
class MyContainer : public std::vector<MyObject>
{
public:
// Redeclare all container traits: value_type, iterator, etc...
// Domain-specific constructors
// (more useful to the user than std::vector ones...)
// Add a few domain-specific helper methods...
// Perhaps modify or hide a few methods (domain-related)
};
I'm aware of the practice of preferring composition to inheritance when reusing a class for implementation -- but there's gotta be a limit! If I were to delegate everything to std::vector, there would be (by my count) 32 forwarding functions!
So my questions are... Is it really so bad to inherit implementation in such cases? What are the risks? Is there a safer way I can implement this without so much typing? Am I a heretic for using implementation inheritance? :)
Edit:
What about making it clear that the user should not use MyContainer via a std::vector<> pointer:
// non_api_header_file.h
namespace detail
{
typedef std::vector<MyObject> MyObjectBase;
}
// api_header_file.h
class MyContainer : public detail::MyObjectBase
{
// ...
};
The boost libraries seem to do this stuff all the time.
Edit 2:
One of the suggestions was to use free functions. I'll show it here as pseudo-code:
typedef std::vector<MyObject> MyCollection;
void specialCollectionInitializer(MyCollection& c, arguments...);
result specialCollectionFunction(const MyCollection& c);
etc...
A more OO way of doing it:
typedef std::vector<MyObject> MyCollection;
class MyCollectionWrapper
{
public:
// Constructor
MyCollectionWrapper(arguments...) {construct coll_}
// Access collection directly
MyCollection& collection() {return coll_;}
const MyCollection& collection() const {return coll_;}
// Special domain-related methods
result mySpecialMethod(arguments...);
private:
MyCollection coll_;
// Other domain-specific member variables used
// in conjunction with the collection.
}
The risk is deallocating through a pointer to the base class (delete, delete[], and potentially other deallocation methods). Since these classes (deque, map, string, etc.) don't have virtual dtors, it's impossible to clean them up properly with only a pointer to those classes:
struct BadExample : vector<int> {};
int main() {
vector<int>* p = new BadExample();
delete p; // this is Undefined Behavior
return 0;
}
That said, if you're willing to make sure you never accidentally do this, there's little major drawback to inheriting them—but in some cases that's a big if. Other drawbacks include clashing with implementation specifics and extensions (some of which may not use reserved identifiers) and dealing with bloated interfaces (string in particular). However, inheritance is intended in some cases, as container adapters like stack have a protected member c (the underlying container they adapt), and it's almost only accessible from a derived class instance.
Instead of either inheritance or composition, consider writing free functions which take either an iterator pair or a container reference, and operate on that. Practically all of <algorithm> is an example of this; and make_heap, pop_heap, and push_heap, in particular, are an example of using free functions instead of a domain-specific container.
So, use the container classes for your data types, and still call the free functions for your domain-specific logic. But you can still achieve some modularity using a typedef, which allows you to both simplify declaring them and provides a single point if part of them needs to change:
typedef std::deque<int, MyAllocator> Example;
// ...
Example c (42);
example_algorithm(c);
example_algorithm2(c.begin() + 5, c.end() - 5);
Example::iterator i; // nested types are especially easier
Notice the value_type and allocator can change without affecting later code using the typedef, and even the container can change from a deque to a vector.
You can combine private inheritance and the 'using' keyword to work around most of the problems mentioned above: Private inheritance is 'is-implemented-in-terms-of' and as it is private you cannot hold a pointer to the base class
#include <string>
#include <iostream>
class MyString : private std::string
{
public:
MyString(std::string s) : std::string(s) {}
using std::string::size;
std::string fooMe(){ return std::string("Foo: ") + *this; }
};
int main()
{
MyString s("Hi");
std::cout << "MyString.size(): " << s.size() << std::endl;
std::cout << "MyString.fooMe(): " << s.fooMe() << std::endl;
}
As everyone has already stated, STL containers do not have virtual destructors so inheriting from them is unsafe at best. I've always considered generic programming with templates as a different style of OO - one without inheritance. The algorithms define the interface that they require. It is as close to Duck Typing as you can get in a static language.
Anyway, I do have something to add to the discussion. The way that I have created my own template specializations previously is to define classes like the following to use as base classes.
template <typename Container>
class readonly_container_facade {
public:
typedef typename Container::size_type size_type;
typedef typename Container::const_iterator const_iterator;
virtual ~readonly_container_facade() {}
inline bool empty() const { return container.empty(); }
inline const_iterator begin() const { return container.begin(); }
inline const_iterator end() const { return container.end(); }
inline size_type size() const { return container.size(); }
protected: // hide to force inherited usage only
readonly_container_facade() {}
protected: // hide assignment by default
readonly_container_facade(readonly_container_facade const& other):
: container(other.container) {}
readonly_container_facade& operator=(readonly_container_facade& other) {
container = other.container;
return *this;
}
protected:
Container container;
};
template <typename Container>
class writable_container_facade: public readable_container_facade<Container> {
public:
typedef typename Container::iterator iterator;
writable_container_facade(writable_container_facade& other)
readonly_container_facade(other) {}
virtual ~writable_container_facade() {}
inline iterator begin() { return container.begin(); }
inline iterator end() { return container.end(); }
writable_container_facade& operator=(writable_container_facade& other) {
readable_container_facade<Container>::operator=(other);
return *this;
}
};
These classes expose the same interface as an STL container. I did like the effect of separating the modifying and non-modifying operations into distinct base classes. This has a really nice effect on const-correctness. The one downside is that you have to extend the interface if you want to use these with associative containers. I haven't run into the need though.
In this case, inheriting is a bad idea: the STL containers do not have virtual destructors so you might run into memory leaks (plus, it's an indication that STL containers are not meant to be inherited in the first place).
If you just need to add some functionality, you can declare it in global methods, or a lightweight class with a container member pointer/reference. This off course doesn't allow you to hide methods: if that is really what you are after, then there's no other option then redeclaring the entire implementation.
Virtual dtors aside, the decision to inherit versus contain should be a design decision based the class you are creating. You should never inherit container functionality just because its easier than containing a container and adding a few add and remove functions that seem like simplistic wrappers unless you can definitively say that the class you are creating is a kind-of the container. For instance, a classroom class will often contain student objects, but a classroom isn't a kind of list of students for most purposes, so you shouldn't be inheriting from list.
It is easier to do:
typedef std::vector<MyObject> MyContainer;
The forwarding methods will be inlined away, anyhow. You will not get better performance this way. In fact, you will likely get worse performance.
Always consider composition over inheritance.
Consider the case:
class __declspec(dllexport) Foo :
public std::multimap<std::string, std::string> {};
Then symbols of std::multimap will be exported into your dll, which may cause compilation error "std::multimap already defined".