C++ Struct that contains a map of itself - c++

Simple question: How do I get this to work?
struct A {
double whatever;
std::unordered_map<std::string, A> mapToMoreA;
}
g++ error: std::pair<_T1, _T2>::second has incomplete type
As far as I understand, when instantiating the map, the compiler needs to know the size of A, but it doesn't know this because the map is declared in A's declaration, so is the only way to get around this to use pointers to A (don't feel like doing that)?

Most of the time it will depend on the container implementation details (more precisely, on what gets instantiated at the point of container declaration and what doesn't). Apparently, std::unordered_map implementation requires the types to be complete. At the same time GCC's implementation of std::map compiles perfectly fine with incomplete type.
To illustrate the source of such difference, consider the following example. Let's say we decided to make our own naive implementation of std::vector-like functionality and declared our vector class as follows
template <typename T> class my_vector {
T *begin;
T *end;
...
};
As long as our class definition contains only pointers to T, the type T is not required to be complete for the class definition itself. We can instantiate my_vector itself for an incomplete T without any problems
class X;
my_vector<X> v; // OK
The "completeness" of the type would be required later, when we begin to use (and therefore instantiate) the individual methods of my_vector.
However, if for some reason we decide to include a direct instance of T into our vector class, things will chahge
template <typename T>
class my_vector {
T *begin;
T *end;
T dummy_element;
...
};
Now the completeness of T will be required very early, at the point of instantiation of my_vector itself
class X;
my_vector<X> v; // ERROR, incomplete type
Something like that must be happening in your case. The definition of unordered_map you are dealing with somehow contains a direct instance of A. Which is the reason why it is impossible to instantiate (obviously, you would end up with infinitely recursive type in that case).
A better thought through implementation of unordered_map would make sure not to include A into itself as a direct member. Such implementation would not require A to be complete. As you noted yourself, Boost's implementation of unordered_map is designed better in this regard.

I don't know of any STL containers other than smart pointers that work with incomplete types. You can use a wrapper struct however if you don't want to use pointers:
struct A {
struct B { double whatever; };
std::unordered_map<std::string, B> mapToB;
};
Edit: Here is a pointer alternative if the above doesn't meet your use case.
struct A {
double whatever;
std::unordered_map<std::string, std::unique_ptr<A>> mapToMoreA;
};
You can also just use boost::unordered_map which not only supports incomplete types but also has far greater debug performance in Visual Studio as Microsoft's implementation of std::unordered_map is incredibly inefficient due to excessive iterator debugging checks. I am unaware of any performance concerns on gcc for either container.

Boost.Variant has a handy utility explicitly for this purpose – boost::recusive_wrapper<>. The following should work:
struct A {
double whatever;
std::unordered_map<std::string, boost::recursive_wrapper<A>> mapToMoreA;
};
The only notable drawback is that Boost.Variant has not yet been updated to support C++11 move semantics. Update: added in Boost 1.56.

If having the map hold pointers isn't acceptable, perhaps this will work for you:
struct A {
struct hidden;
std::unique_ptr<hidden> pimpl;
};
struct A::hidden {
double whatever;
std::unordered_map<std::string, A> mapToMoreA;
};

In C++ you usually use pointers, which have predefined constant size, for incomplete types:
This of course changes how you use the map: you'll have to dereference with the * or -> operators to access members and have to delete the pointers at some point.
struct A
{
double bla;
std::map<std::string, A*> mapToMoreA;
};
Member functions of A should be split into a prototype inside the struct block and implemented later, otherwise A and its members are not yet completely defined:
struct A
{
double bla;
std::map<std::string, A*> mapToMoreA;
void doStuff(const std::string& str);
};
void A::doStuff(const std::string& str)
{
mapToMoreA[str] = new A();
}

Or use a pointer to the map. The pointer must be of type void* in this case (can be hidden behind a set of functions). Maybe there are alternatives to std::unordered_map that can cope with incomplete value types.

I think you can just forward declare struct A; prior to its definition and the compiler should be happy.
EDIT: So after being downvoted several times, I wrote the following to see what I was missing:
#include <boost/unordered_map.hpp>
#include <string>
#include <iostream>
struct A;
struct A {
double whatever;
boost::unordered_map<std::string, A> mapToMoreA;
};
int main(void)
{
A b;
b.whatever = 2.5;
b.mapToMoreA["abc"] = b;
std::cerr << b.mapToMoreA["abc"].whatever << std::endl;
return 0;
}
This compiles fine using g++ 4.2.1 on my mac, and prints out "2.5" when it's run (as expected).
Sorry that I don't have unordered_map without boost. Is that the issue? (i.e., does std::unordered_map somehow place more constraints on the compiler than boost does?) Otherwise, I'm not sure what I'm missing here about the question. Those downvoting this, please enlighten me with comments. Thanks!

Related

Dealing with circular dependency in std::variant

I'm trying to deal with circular dependency in following scenario:
I've got a std::variant, say:
//types.h
using Types = std::variant<int, double, std::string, SomeClass>;
SomeClass is a pretty simple thing holding few pointers, with some template logic:
#someclass.h
class SomeClass {
// few simple members (pointers and an integer)
void use(Types arg); // note usage of Types here
template<typename T, typename Ts...> // implicitly assuming T == Ts... == Types
void use(T arg, Ts... tail) {
use(arg);
use(tail...);
}
SomeClass(const SomeClass&) = default; // works fine
};
Usually I would forward-declare SomeClass before "using Types...", but it can't be done when it comes to std::variant. I also didn't really found a way to forward-declare the "using" directive.
One way I found was forward-declaring SomeClass and using a pointer to it in Types, but I don't like this idea (SomeClass is a really light object with short lifespan, I'd want to keep it out of heap).
Is there any other way (beside pointers) in C++ to solve this one? I'm running out of ideas.
Thanks :)
EDIT:
The issue actually appears only if I'm trying to use Types before really defining SomeClass, see https://godbolt.org/z/4jzhEd
In the live example you provided, all you need to solve the issue is define SomeStruct after SomeClass.
This way your Types variant will no longer have any incomplete types when SomeStruct is defined. In other words, here is the order:
class SomeClass;
using Types = std::variant<..., SomeClass>;
class SomeClass {
// ... // Types used here, but doesn't need to have all complete types
};
struct SomeStruct {
Types value;
// ...
};
See here for a live example.

Type aliases and incomplete types

I'm probably over reaching here to solve what should be a simple problem. I started this question here:
Getting type of base class at compile time
Basically I'm trying to make the class manage it's own pointer types. I'm wrapping a C library where some structures have reference counting embedded in them, and others do not. Those that don't, I'd like to use shared_ptr. Those that do, I'd like to use intrusive_ptr. I'd like to avoid relying on programmer intellect to ensure the use of the proper wrapper. Eventually, I'd like to add more capability that relies on this behavior, but I'm not there yet.
#Yakk came up with an interesting solution using template type aliases, and I've tried to implement it. Unfortunately I've got myself in a spot where I can't seem to resolve circular references to the compiler's satisfaction. I get an "incomplete type 'Test2' named in nested name specifier" error pointing to the "using pointer=" line. I also get a bizarre "definition differs from declaration in return type" for my definition of Test::f(), but I suspect that might resolve itself once I get the first error resolved.
Most of the references I find on this error type involve sequencing of header files, but even with everything in one file I can't figure out how to order things to make this problem go away.
Any ideas?
#include <iostream>
#include <memory>
template<typename T>
class Pointered: public std::enable_shared_from_this<T>
{
public:
using pointer=std::shared_ptr<T>; //<-- incomplete type named error
using weakPointer = std::weak_ptr<T>;
};
template<typename T>
using Ptr = typename T:: pointer;
template<typename T>
using WkPtr = typename T:: weakPointer;
class Test2;
class Test:public Pointered<Test>
{
public:
Ptr<Test2> f();
};
class Test2:public Pointered<Test2>
{
public:
Ptr<Test> p;
Test2(Ptr<Test> ptr):p(ptr){}
};
int main(int argc, const char * argv[])
{
Ptr<Test> p=std::make_shared<Test>();
Ptr<Test> p3=p;
p->f();
std::cout << "Refcount: " << p.use_count() << std::endl;
}
//definition differs from declaration in return type error here
Ptr<Test2> Test::f()
{
return Ptr<Test2>(new Test2((Ptr<Test>)shared_from_this()));
}
You cannot forward declare nested types, for that you need the definition of the enclosing type, but in your case you have a cyclic dependency that inhibits this.
The first thing to consider is whether the cyclic dependency is really a good idea. In most cases cyclic dependencies are considered a code smell (an indication of problems with the design). If you can remove the cyclic dependency, then everything will become easier.
A different alternative is moving the dependency on the nested type to a type-trait, that can be defined externally and before the definition of the types:
template <typename T>
struct pointer_traits;
template <>
struct pointer_traits<Test1> {
typedef std::shared_ptr<Test1> ptr;
typedef std::shared_ptr<Test1> wptr;
};
By moving the dependency outside of the real type, you no longer have the cyclic dependency (at the syntax level, you should still revisit the design). You can then add syntactic sugar as needed:
template <typename T>
using ptr = typename pointer_traits<T>::ptr;
class Test1 {
ptr<Test2> p2;
};
If you really want the types to also be nested, you can use inheritance to bring those into scope, or in a simpler way just add the appropriate typedef:
class Test1 {
typedef ptr<Test1> ptr_t;
// ...
Note, this is a rough approximation, if you opt for this approach you can work a bit on the details of the trait and the types to make it sweeter by adding more syntactic sugar, for example, you can provide two traits for shared_ptr_traits and intrusive_ptr_traits and provide a single line trait to determine from which of those you want to pull the typedefs, reducing the definition of the trait (per type) to a single line.

c++ List of classes without initializing them for use of static functions

I may be asking this in a odd way, but I'm not sure how else to ask.
I want to have a list of classes, not objects.
This way I can call static functions without have to create the object.
I would really prefer function pointers at this point:
struct A
{
void SomeFunc(int);
};
struct B
{
void AnotherFunc(int);
};
typedef void (*Function)(int);
std::vector<Function> vec;
vec.push_back(A::SomeFunc); vec.push_back(B::AnotherFunc);
for (Function f: vec)
{
f(2);
}
Note that a static function is more or less equivalent to a traditional C-function (it just got to access some more scope).
What you are looking for are boost typelists. I would however not recommend diving into the Boost MPL if you are not already very experienced with templates, and know how many of their intricacies work.
Now for a simple home-made implementation:
struct Null {};
template <typename Type, typename Next>
struct List
{
typedef Type Type;
typedef Next Next;
};
//Now you can make lists like so:
typedef List<int, List<float List<short, Null> > > MyList;
From there use recursive Templated implementations to call the static methods you want.
If you want more information on these kinds of techniques, you should read Modern C++ Design
As a solution you can create a list of method pointers
I don't think what you are asking is possible, at least not in the way you think. You cannot have a variable, array, container class or any other storage of type names. So you cannot do something like
ListOfClasses[n]::someStaticMember(...);
in C++. It is impossible.
http://www.boost.org/doc/libs/1_45_0/libs/mpl/doc/refmanual/refmanual_toc.html
eg:
typedef vector<C1,C2,C3> types;
at_c<types,0>::type::method();
...

Advantages of an empty class in C++

What could be the possible advantages/uses of having an empty class?
P.S:
This question might sound trivial to some of you but it is just for learning purpose and has no practical significance. FYI googling didn't help.
One use would be in template (meta-)programming: for instance, iterator tags are implemented as empty classes. The only purpose here is to pass around information at compilation time so you can check, if an iterator passed to e.g. a template function meets specific requirements.
EXAMPLE:
This is really simplified, just to ge an idea. Here the purpose of the tag class is to decide, which implementation of an algorithm to use:
class forward_iterator_tag {};
class random_access_iterator_tag {};
class MySimpleForwardIterator {
public:
typedef typename forward_iterator_tag tag;
// ...
};
class MySimpleRandomIterator {
public:
typedef typename random_access_iterator_tag tag;
// ...
};
template<class iterator, class tag>
void myfunc_int(iterator it, tag t) {
// general implementation of myfunc
}
template<class iterator>
void myfunc_int<iterator, forward_iterator_tag>(iterator it) {
// Implementation for forward iterators
}
template<class iterator>
void myfunc_int<iterator, random_access_iterator_tag>(iterator it) {
// Implementation for random access iterators
}
template<class iterator>
void myfunc(iterator it) {
myfunc_int<iterator, typename iterator::tag>(it);
}
(I hope I got this right, it's been a while since I used this ...)
With this code, you can call myfunc on an arbitrary iterator, and let the compiler choose the correct implementation depending on the iterator type (i.e. tag).
The following can be used to have a boost::variant which can hold an (SQL) NULL value for example.
class Null { };
typedef boost::variant<Null, std::string, int> Value;
To make it more useful things like operator== and operator<< are handy. For example:
std::ostream& operator<<(std::ostream &lhs, const Null &rhs)
{
lhs << "*NULL*";
return lhs;
}
int main()
{
Variant v("hello");
std::cout << v << std::endl;
v = Null();
std::cout << v << std::endl;
...
}
Will give:
hello
*NULL*
In the STL, Standard Template Library of the C++, for example you have
template<class _Arg,
class _Result>
struct unary_function
{ // base class for unary functions
typedef _Arg argument_type;
typedef _Result result_type;
};
When defining a functor, you can inherit unary_function, and then you have the typedef defined automatically at your disposal.
An empty class could be used as a "token" defining something unique; in certain patterns, you want an implementation-agnostic representation of a unique instance, which has no value to the developer other than its uniqueness. One example is Unit of Work; you may not care one bit about what's going on inside your performer, but you want to tell that performer that the tasks you're telling it to perform are part of an atomic set. An empty class representing the Unit of Work to the outside world may be perfect in this case; almost anything a Unit of Work object could store or do (encapsulating a DB transaction, exposing Commit/Rollback behaviors) would start tying you to a particular implementation, but an object reference is useful to provide a unique but copyable and passable reference to the atomic set of tasks.
You can use it like a placeholder for checking purpose or as enabler to special functionality. For example in Java exist the "empty" interface Serializable used to specify if a class is serializable.
"empty" classes means classes which have no data members?
They typically declare typedefs or member functions, and you can extend them with your own classes.
Here is an interesting link with answers to why its allowed. You might find this helpful to find situations where it might be useful.
As others have said, often an empty class (or struct) is used a placeholder, a differentiator, a token, etc.
For example, a lot of people are unaware that there are "nothrow" versions of operator new. The syntax to invoke nothrow new is:
p = new(std::nothrow) Bar;
and std::nothrow is defined simply as
struct nothrow_t {}; //defined in namespace std
The answer by MartinStettner is fine though just to highlight an important point here: The concept of iterator tags or for that matter any tags in C++, is not strictly dependent on empty classes. The C++ tags, if stl writers would have wanted to, could well have been non-empty classes; that should work but then it won't add any additional value; at least for compile time acrobatics that it is usually reserved for.
For the sake of typeid
Suppose we have comparable interface Id. We need fill some container with unique instances of this interface. How to guarantee the uniqueness of Id instances produced by independent software parts? «Independent parts» means some different dynamic libraries, compiled by different programmers from different locations
One of decisions is to compare typeid of some type first. If typeid matches, convert and compare other implementation specific properties. C++ language guarantees uniqueness of any type within process memory. Which type should be used for this purpose? Any type with minimum resource consumption — empty one

Getting a vector<Derived*> into a function that expects a vector<Base*>

Consider these classes.
class Base
{
...
};
class Derived : public Base
{
...
};
this function
void BaseFoo( std::vector<Base*>vec )
{
...
}
And finally my vector
std::vector<Derived*>derived;
I want to pass derived to function BaseFoo, but the compiler doesn't let me. How do I solve this, without copying the whole vector to a std::vector<Base*>?
vector<Base*> and vector<Derived*> are unrelated types, so you can't do this. This is explained in the C++ FAQ here.
You need to change your variable from a vector<Derived*> to a vector<Base*> and insert Derived objects into it.
Also, to avoid copying the vector unnecessarily, you should pass it by const-reference, not by value:
void BaseFoo( const std::vector<Base*>& vec )
{
...
}
Finally, to avoid memory leaks, and make your code exception-safe, consider using a container designed to handle heap-allocated objects, e.g:
#include <boost/ptr_container/ptr_vector.hpp>
boost::ptr_vector<Base> vec;
Alternatively, change the vector to hold a smart pointer instead of using raw pointers:
#include <memory>
std::vector< std::shared_ptr<Base*> > vec;
or
#include <boost/shared_ptr.hpp>
std::vector< boost::shared_ptr<Base*> > vec;
In each case, you would need to modify your BaseFoo function accordingly.
Instead of passing the container object (vector<>), pass in begin and end iterators like the rest of the STL algorithms. The function that receives them will be templated, and it won't matter if you pass in Derived* or Base*.
This problem occurs in programming languages that have mutable containers. You cannot pass around a mutable bag of apples as a bag of fruit because you cannot be sure that someone else does not put a lemon into that bag of fruit, after which it no longer qualifies as a bag of apples. If the bag of apples were not mutable, passing it around as a bag of fruit would be fine. Search for covariance/contravariance.
one option is to use a template
template<typename T>
void BaseFoo( const std::vector<T*>& vec)
{
...
}
The drawback is that the implementation has to be in the header and you will get a little code bloat. You will wind up with different functions being instantiated for each type, but the code stays the same. Depending on the use case it's a quick and dirty solution.
Edit, I should note the reason we need a template here is because we are trying to write the same code for unrelated types as noted by several other posters. Templates allow you do solve these exact problems. I also updated it to use a const reference. You should also pass "heavy" objects like a vector by const reference when you don't need a copy, which is basically always.
Generally you would start with a container of base pointers, not the other way.
If you dealing with a third-party library, and this is your only hope, then you can do this:
BaseFoo (*reinterpret_cast<std::vector<Base *> *>(&derived));
Otherwise fix your code with one of the other suggesstions.
Taking Matt Price's answer from above, given that you know in advance what types you want to use with your function, you can declare the function template in the header file, and then add explicit instantiations for those types:
// BaseFoo.h
template<typename T>
void BaseFoo( const std::vector<T*>& vec);
// BaseFoo.cpp
template<typename T>
void BaseFoo( const std::vector<T*>& vec);
{
...
}
// Explicit instantiation means no need for definition in the header file.
template void BaseFoo<Base> ( const std::vector<Base*>& vec );
template void BaseFoo<Derived> ( const std::vector<Derived*>& vec );
If std::vector supported what you're asking for, then it would be possible to defeat the C++ type system without using any casts (edit: ChrisN's link to the C++ FAQ Lite talks about the same issue):
class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};
void pushStuff(std::vector<Base*>& vec) {
vec.push_back(new Derived2);
vec.push_back(new Base);
}
...
std::vector<Derived1*> vec;
pushStuff(vec); // Not legal
// Now vec contains a Derived2 and a Base!
Since your BaseFoo() function takes the vector by value, it cannot modify the original vector that you passed in, so what I wrote would not be possible. But if it takes a non-const reference and you use reinterpret_cast<std::vector<Base*>&>() to pass your std::vector<Derived*>, you might not get the result that you want, and your program might crash.
Java arrays support covariant subtyping, and this requires Java to do a runtime type check every time you store a value in an array. This too is undesirable.
They are unrelated types -- you can't.