This is my (maybe a little bit weird) thought, suppose I want to define a std::set object to contain some stuff for later use, but unfortunately I'm not sure which type will be passed to std::set<not-sure> as template arg, and this not-sure type will be determined through a string, like this:
class X {
public:
foo()
{
char not_sure_type[20];
scanf("%s", not_sure_type);
if (strcmp(not_sure_type, "int"))
// then std::set<int>
else if (// "char")
// then std::set<char>
}
private:
void * _set;
};
This way, I can determine that std::set<int> will be instantiated or not, right? But how can I tell _set that you should point to a std::set<int>? Without knowing that, either I cannot use static_cast to cast _set from void * to std::set<int>*, back and forth.
So can I save the std::set<int> just like an data member for later use?
Any idea is appreciated.
If you will know the the type of the set element at run-time (based on a say string), you could maybe store a pointer to an abstract type into the set (set), and then use an Abstract Factory in the constructor of the class that holds the std::set to instantiate the actual Concrete Types for the elements during run-time based on the provided string.
The problem is in using raw pointers here, since you will need to do the cleanup within the class that has std::set. Since you want to use std::set, make sure that your Concrete Type for the element is Comparable. Not sure if this is the right way to go though.. you said to throw in ideas...
sounds to me like you are considering using c++ as a weak type language, such as python. sure there could be workarounds like using some abstract base class etc. but the bottom line I think is that defining the type at run time is against the paradigm of c++..
Related
I am trying to implement a C++ class which will wrap a value (among other things). This value may be one of a number of types (string, memory buffer, number, vector).
The easy way to implement this would be to do something like this
class A {
Type type;
// Only one of these will be valid data; which one will be indicated by `type` (an enum)
std::wstring wData{};
long dwData{};
MemoryBuffer lpData{};
std::vector<std::wstring> vData{};
};
This feels inelegant and like it wastes memory.
I also tried implementing this as a union, but it came with significant development overhead (defining custom destructors/move constructors/copy constructors), and even with all of those, there were still some errors I encountered.
I've also considered making A a base class and making a derived class for each possible value it can hold. This also feels like it isn't a great way to solve the problem.
My last approach would be to make each member an std::optional, but this still adds some overhead.
Which approach would be the best? Or is there another design that works better than any of these?
Use std::variant. It is typesafe, tested and exactly the right thing for a finite number of possible types.
It also gets rid of the type enum.
class A {
std::variant<std::wstring, long, MemoryBuffer, std::vector<std::wstring>> m_data{}; // default initializes the wstring.
public
template<class T>
void set_data(T&& data) {
m_data = std::forward<T>(data);
}
int get_index() { // returns index of type.
m_data.index();
}
long& get_ldata() {
return std::get<long>(m_data); // throws if long is not the active type
}
// and the others, or
template<class T>
T& get_data() { // by type
return std::get<T>(m_data);
}
template<int N>
auto get_data() { // by index
return std::get<N>(m_data);
}
};
// using:
A a;
a.index() == 0; // true
a.set_data(42);
a.index() == 1; // true
auto l = a.get<long>(); // l is now of type long, has value 42
a.get<long>() = 1;
l = a.get<1>();
PS: This example does not even include the coolest (in my opinion) feature of std::variant: std::visit I am not sure what you want to do with your class, so I cannot create a meaningful example. If you let me know, I will think about it.
You basically want QVariant without the rest of Qt, then :)?
As others have mentioned, you could use std::variant and put using MyVariant = std::variant<t1, t2, ...> in some common header, and then use it everywhere it's called for. This isn't as inelegant as you may think - the specific types to be passed around are only provided in one place. It is the only way to do it without building a metatype machinery that can encapsulate operations on any type of an object.
That's where boost::any comes in: it does precisely that. It wraps concepts, and thus supports any object that implements these concepts. What concepts are required depends on you, but in general you'd want to choose enough of them to make the type usable and useful, yet not too many so as to exclude some types prematurely. It's probably the way to go, you'd have: using MyVariant = any<construct, _a>; then (where construct is a contract list, an example of which is as an example in the documentation, and _a is a type placeholder from boost::type_erasure.
The fundamental difference between std::variant and boost::any is that variant is parametrized on concrete types, whereas any is parametrized on contracts that the types are bound to. Then, any will happily store an arbitrary type that fulfills all of those contracts. The "central location" where you define an alias for the variant type will constantly grow with variant, as you need to encapsulate more type. With any, the central location will be mostly static, and would change rarely, since changing the contract requirements is likely to require fixes/adaptations to the carried types as well as points of use.
Traditionally, I've programmed in c++ and Java, and I'm now beginning to learn ruby.
My question then is, how do languages like ruby internally implement their array and hash data structures in such a way that they can hold any type at the same time? I know that in Java, the fact that every class is derived from object, could be one way to implement this, but I was wondering if there was another way. For example, in c++, if I wanted to implement a dynamic array that could simultaneously hold multiple types of values (of no relation), how could I do this?
To clarify, I'm not referring to generic programming or templates, as those simply create a new collection interface for a type. I'm referring to a structure such as this:
array = [1, "hello", someClass];
Most of them do roughly the same as you'd get in C++ by creating a vector (or list, deque, etc.) of boost::any, or something similar.
That is to say, they basically attach some tag to each type of object as it's stored in memory. When they store an object, they store the tag. When they read an object, they look at the tag to figure out what kind of object that is. Of course, they also handle most of this internally, so you don't have to write the code to figure out what kind of object you've just retrieved from the collection.
In case it's not clear: the "tag" is just a unique number assigned to each type. If the system you're dealing with has primitive types, it'll normally pre-assign a type number to each of them. Likewise, each class you create gets a unique number assigned to it.
To do that in C++, you'd normally create a central registry of tags. When you register a type, you receive a unique number back that you use to tag objects of that type. When a language supports this directly, it automates the process of registering types and choosing a unique tag for each.
Although this is probably the most common method of implementing such things, it's definitely not the only one. Just for example, it's also possible to designate specific ranges of storage for particular types. When you allocate an object of a given type, it's always allocated from that type's address range. When you create a collection of "objects", you're really not storing the objects themselves, but instead storing something that contains the address of the object. Since objects are segregated by address you can figure out the type of the object based on the value of the pointer.
In the MRI interpreter, a ruby value is stored as a pointer type which points to a data structure storing the class of the value and any data associated with the value. Since pointers are always the same size, (sizeof(unsigned long) usually), it is possible. To answer your question about C++, it is impossible in C++ to determine the class of an object given it's location in memory, so it wouldn't be possible unless you had something like this:
enum object_class { STRING, ARRAY, MAP, etc... };
struct TaggedObject {
enum object_class klass;
void *value;
}
and passed around TaggedObject * values. That is pretty much what ruby does internally.
There are many ways to do that :-
You can define a common interface for all the elements and make a container of those. For example:
class Common { /* ... */ }; // the common interface.
You can use container of void* :-
vector<void*> common; // this would rather be too low level.
// you have to use cast very much.
And then the best approach I think is using an Any class, such as Boost::Any :-
vector<boost::any> v;
You're looking for something called type erasure. The simplest way to do this in C++ is with boost::any:
std::vector<boost::any> stuff;
stuff.push_back(1);
stuff.push_back(std::string("hello"));
stuff.push_back(someClass);
Of course with any, you're extremely limited in what you can do with your stuff since you have to personally remember everything you put into it.
A more common use-case of heterogeneous containers might be a series of callbacks. The standard class std::function<R(Args...)> is, in fact, a type-erased functor:
void foo() { .. }
struct SomeClass {
void operator()() { .. }
};
std::vector<std::function<void()>> callbacks;
callbacks.push_back(foo);
callbacks.push_back(SomeClass{});
callbacks.push_back([]{ .. });
Here, we're adding three objects of different types (a void(*)(), a SomeClass, and some lambda) to the same container - which we do by erasing the type. So we can still do:
for (auto& func : callbacks) {
func();
}
And that will do the right thing in each of the three objects... no virtuals needed!
Others have explained ways you can do this in C++.
There are various ways to solve this problem. To answer your question about how does languages such as Ruby solve this, without going into details of exactly how Ruby solves it, they use a structure that contains type information. For example, we could do that in C++ something like this:
enum TypeKind { None, Int, Float, String }; // May need a few more?
class TypeBase
{
protected:
TypeKind kind;
public:
TypeBase(TypeKind k) : kind(k) { }
virtual ~TypeBase() {};
TypeKind type() { return kind; }
};
class TypeInt : public TypeBase
{
private:
int value;
public:
TypeInt(int v) : value(v), TypeBase(Int) {}
};
class TypeFloat : public TypeBase
{
private:
double value;
public:
TypeFloat(double v) : value(v), TypeBase(Float) {}
};
class TypeString : public TypeBase
{
private:
std::string value;
public:
TypeString(std::string v) : value(v), TypeBase(String) {}
};
(To make it useful, we probably need some more methods for the TypeXxx class, but I don't feel like typing for another hour... ;) )
And then somewhere, it determines the type, e.g.
Token t = getNextToken();
TypeBase *ty;
if (t.type == IntegerToken)
{
ty = new(TypeInt(stoi(t.str));
}
else if (t.type == FloatToken)
{
ty = new(TypeFloat(stod(t.str));
}
else if (t.type == StringToken)
{
ty = new(TypeString(t.str));
}
Of course, we'd also need to deal with variables and various other scenarios, but the essence of it is that the language can keep track of (and sometimes mutate) the value that is stored.
Most languages in the general category where Ruby, PHP, Python, etc are, will have this sort of mechanism, and all variables are stored in some sort of indirect way. The above is just one possible solution, I can think of at least half a dozen other ways to do this, but they are variations on the theme of "store data together with type information".
(And by the way, boost::any also does something along the lines of the above, more or less....)
In Ruby, the answer is rather simple: that array doesn't contain values of different types, they are all of the same type. They are all objects.
Ruby is dynamically typed, the idea of an array that is statically constrained to only hold elements of the same type doesn't even make sense.
For a statically typed language, the question is, how much do you want it to be like Ruby? Do you want it to be actually dynamically typed? Then you need to implement a dynamic type in your language (if it doesn't already have one, like C♯’s dynamic).
Otherwise, if you want a statically typed heterogenous list, such a thing is usually called an HList. There's a very nice implementation for Scala in the Shapeless library, for example.
Function1 can be called with any type T which will be converted to (void*) to be able to add to the list but with this I lose the original pointer type (I need t store tham in one linkedlist because I cannot create one for every possible type). So somehow I need to save the type of the pointer as well. I know that it cant be done using c++. Can anyone suggest an alternative solution?
class MyClass
{
template<class T>
void function1(T* arg1)
{
myList.add((void*)arg);
}
void function2()
{
for(int i = 0; i < myList.size(); i++)
{
myList.get(i);
//restore the original pointer type
}
}
STLinkedlist<void*> myList;
}
The usual way to handle these kinds of problems is by using a public interface, in C++ this is done through inheritance. This can be a drag, especially in constrained situations, where a full class/interface hierarchy would provide too much code/runtime overhead.
In comes Boost.Variant, which allows you to use the same object to store different types. If you need even more freedom, use Boost.Any. For a comparison, see e.g. here.
At the end of the day (or better: rather sooner than later), I'd try to do things differently so you don't have this problem. It may well be worth it in the end.
If you lost the type info by going void* it is just gone. You can not just restore it.
So you either must store extra information along with the pointer, then use branching code to cast it back, or rather drive design to avoid the loss.
Your case is pretty suspicious that you do not what you really want.
A more usual case is that you want a polymorphic collection. That doesn't store any kind of pointers but those belonging to the same hierarchy. Collection has Base* pointers, and you can use the objects through Base's interface, all calling the proper virtual function without programmer's interaction. And if you really need to cast to the original type you can do it via dynamic_cast safely. Or add some type info support in the base interface.
Function1 can be called with any type T which will be converted to (void*) to be able to add to the list but with this I lose the original pointer type (I need t store tham in one linkedlist because I cannot create one for every possible type).
You're having the XY problem. The solution is not to decay your pointers to void* and store type information.
You simply can create a type for every possible type - you create a template type. You need to define an abstract interface for your "type for every object", then define a template class implementing this interface, that is particularized by type. Finally, you create your custom-type instance on your type of pointer received and store them by base class pointer (where the base class is your interface definition).
All that said, you (normally) shouldn't need to implement this at all, because the functionality is already implemented in boost::any or boost::variant (you will have to choose one of them).
General
Take into consideration, that if you want to store different objects inside a std::vector<void *>, mostly likely your application has a bad design. In this case, I'd think, whether it is really necessary to do it (or how can it be done in another way), rather than searching for the solution, how to do it.
However, there are no fully evil things in C++ (nor in any other language), so if you are absolutely certain, that this is the only solution, here are three possible ways to solve your problem.
Option 1
If you store only pointers to simple types, store the original type along with the pointer by an enum value or simply a string.
enum DataType
{
intType,
floatType,
doubleType
};
std::vector<std::pair<void *, DataType>> myData;
Option 2
If you store mixed data (classes and simple types), wrap your data in some kind of class.
class BaseData
{
public:
virtual ~BaseData() { }
};
class IntData : public BaseData
{
public:
int myData;
};
std::vector<BaseData *> myData;
Later, you'll be able to check the type of your data using dynamic_cast.
Option 3
If you store only classes, store them simply as a pointer to their base class and dynamic_cast your way out.
You could use boost::any to store any type in your list instead of use void*. It's not exactly what you want but I don't think you can restore the type in run time (as Kerrek said, it's not Java).
class MyClass
{
template<class T>
void function1(T arg1)
{
myList.add(arg);
}
template<class T>
T get(int i)
{
return boost::any_cast<T>(myList.get(i));
}
STLinkedlist<boost::any> myList;
};
Before I was trying to map my classes and namespaces, by using static calls I succeded and now I need to map the functions of my classes because they will be used dynamically.
Firstly I was thinking to hardcode in the constructor so I can assign a std:map with the string of the name of function pointing to the function itself.
for example:
class A{
int B(){
return 1;
}
};
int main(){
A *a = new A();
vector<string, int (*)()> vec;
vector["A.B"] = a.B;
}
By that I have mapped the function B on A class, I know that I only mapped the function the instance and thats B is not static to be globally mapped.
But thats what I need, at somepoint someone will give me a string and I must call the right function of an instance of a class.
My question is if I only can do that by hardcoding at the constructor, since this is a instance scope we are talking or if there is somehow a way to do this in the declaration of the function, like here for namespaces and classes:
Somehow register my classes in a list
If I understand you correctly, you want your map to store a pointer that can be used to call a member function on an instance, the value being chosen from the map at run time. I'm going to assume that this is the right thing to do, and that there isn't a simpler way to solve the same problem. Quite often when you end up in strange C++ backwaters it's a sign that you need to look again at the problem you think you have, and see whether this is the only way to solve it.
The problem with using an ordinary function pointer is that a non-static member function is not an ordinary function. Suppose you could point to a member function with an ordinary function pointer, what would happen when you dereferenced that pointer and called the function? The member function needs an object to operate on, and the syntax doesn't provide a way to pass this object in.
You need a pointer to member, which is a slightly obscure feature with relatively tricky syntax. While an ordinary pointer abstracts an object, a pointer to member abstracts a member on a class; the pointer specifies which class member should be called, but not which object to obtain the member from (that will be specified when the pointer is used). We can use it something like this:
class B;
class A
{
B some_function()
{ /* ... */ }
};
B (A::* myval)() = A::some_function;
Here myval is a variable that indicates one of the members of class A, in this case the member some_function (though it could point to any other member of A of the same type). We can pass myval round wherever we want (e.g. storing it in an STL container, as in your example) and then when we want to call the function, we specify the instance it should be called on in order to locate the function:
A some_a;
B newly_created_b = (some_a.*myval)();
This works for a particular case, but it won't solve your general issue, because member pointers contain the class they refer to as part of the definition. That is, the following two variables are of entirely different types:
B (Foo::* first_variable)() = Foo::some_function;
B (Bar::* second_variable)() = Bar::some_function;
Even though both functions can produce a B when called without arguments, the two values operate on different classes and therefore you can't assign a value of one type to a variable of the other type. This of course rules out storing these different types in a single STL container.
If you're committed to storing these in a container, you'll have to go with a functor-based solution like Charles Salvia proposes.
If I understand you correctly, you're going to have a class like:
struct Foo
{
int bar();
};
And the user will input a string like "Foo::bar", and from that string you need to call the member function Foo::bar?
If so, it's rather awkward to code a flexible solution in C++, due to the static type system. You can use an std::map where the key is a string, and the value is a member function pointer, (or std::mem_fun_t object), but this will only work on a single class, and only on member functions with the same signature.
You could do something like:
#include <iostream>
#include <map>
#include <functional>
struct Foo
{
int bar() { std::cout << "Called Foo::bar!" << std::endl; }
};
int main()
{
std::map<std::string, std::mem_fun_t<int, Foo> > m;
m.insert(std::make_pair("Foo::bar", std::mem_fun(&Foo::bar)));
Foo f;
std::map<std::string, std::mem_fun_t<int, Foo> >::iterator it = m.find("Foo::bar");
std::mem_fun_t<int, Foo> mf = it->second;
mf(&f); // calls Foo::bar
}
just found(using google) a topic to the same question I had with an answer.
What is the simplest way to create and call dynamically a class method in C++?
I didn't try it yet but makes sense, I will ask again later if it doesn't work
ty!
Joe
I must call the right function of an instance of a class.
You need to call a specific method on an existing instance, or you need to create an instance of the appropriate type and call the method?
If it's the former, then you need a std::map or similar that lets you look up instances from their names.
If it's the latter, that's basically what serialization frameworks need to do in order to create the correct type of object when de-serializing, the object that knows how to read the next bit of data. You might take a look at how the Boost serialization library handles it:
boost.org/doc/libs/1_40_0/libs/serialization/doc/serialization.html
Are you doing this in some kind of tight loop where you need the efficiency of a good map? If so, then member function pointers (as you linked to above) is a good way to go. (At least it is after you work around the problem #Tim mentioned of keeping member function pointers to different types in the same collection ... let the language abuse begin!)
On the other hand, if this is in code that's user-driven, it might be more legible to just be totally uncool and write:
if( funcName=="A.b" )
{
A a;
a.b();
} else
// etc etc etc
For the higher-performace case, you can supplement the same approach with a parse step and some integer constants (or an enum) and use a switch. Depending on your compiler, you might actually end up with better performance than using member function pointers in a map:
switch( parse(funcName) )
{
case A_b:
{
A a;
a.b();
}
break;
}
(Of course this breaks down if you want to populate your list of possibilities from different places ... for example if each class is going to register itself during startup. But if you have that kind of object infrastructure then you should be using interfaces instead of pointers in the first place!)
I'm trying to teach myself C++, and one of the traditional "new language" exercises I've always used is to implement some data structure, like a binary tree or a linked list. In Java, this was relatively simple: I could define some class Node that maintained an instance variable Object data, so that someone could store any kind of object in every node of the list or tree. (Later I worked on modifying this using generics; that's not what this question is about.)
I can't find a similar, idiomatic C++ way of storing "any type of object." In C I'd use a void pointer; the same thing works for C++, obviously, but then I run into problems when I construct an instance of std::string and try to store it into the list/tree (something about an invalid cast from std::string& to void*). Is there such a way? Does C++ have an equivalent to Java's Object (or Objective-C's NSObject)?
Bonus question: If it doesn't, and I need to keep using void pointers, what's the "right" way to store a std::string into a void*? I stumbled upon static_cast<char*>(str.c_str()), but that seems kind of verbose for what I'm trying to do. Is there a better way?
C++ does not have a base object that all objects inherit from, unlike Java. The usual approach for what you want to do would be to use templates. All the containers in the standard C++ library use this approach.
Unlike Java, C++ does not rely on polymorphism/inheritance to implement generic containers. In Java, all objects inherit from Object, and so any class can be inserted into a container that takes an Object. C++ templates, however, are compile time constructs that instruct the compiler to actually generate a different class for each type you use. So, for example, if you have:
template <typename T>
class MyContainer { ... };
You can then create a MyContainer that takes std::string objects, and another MyContainer that takes ints.
MyContainer<std::string> stringContainer;
stringContainer.insert("Blah");
MyContainer<int> intContainer;
intContainer.insert(3342);
You can take a look at boost::any class. It is type safe, you can put it into standard collections and you don't need to link with any library, the class is implemented in header file.
It allows you to write code like this:
#include <list>
#include <boost/any.hpp>
typedef std::list<boost::any> collection_type;
void foo()
{
collection_type coll;
coll.push_back(boost::any(10));
coll.push_back(boost::any("test"));
coll.push_back(boost::any(1.1));
}
Full documentation is here: http://www.boost.org/doc/libs/1_40_0/doc/html/any.html
What you are looking for are templates. They allow you to make classes and function which allow you to take any datatype whatsoever.
Templates are the static way to do this. They behave like Java and C# generics but are 100% static (compile time). If you d'ont need to store different types of objetcs in the same container, use this (other answers describe this very well).
However, if you need to store different types of objects in the same container, you can do it the dynamic way, by storing pointers on a base class. Of course, you have to define your own objects hierarchy, since there is no such "Object" class in C++ :
#include <list>
class Animal {
public:
virtual ~Animal() {}
};
class Dog : public Animal {
public:
virtual ~Dog() {}
};
class Cat : public Animal {
public:
virtual ~Cat() {}
};
int main() {
std::list<Animal*> l;
l.push_back(new Dog);
l.push_back(new Cat);
for (std::list<Animal*>::iterator i = l.begin(); i!= l.end(); ++i)
delete *i;
l.clear();
return 0;
}
A smart pointer is easier to use. Example with boost::smart_ptr:
std::list< boost::smart_ptr<Animal> > List;
List.push_back(boost::smart_ptr<Animal>(new Dog));
List.push_back(boost::smart_ptr<Animal>(new Cat));
List.clear(); // automatically call delete on each stored pointer
You should be able to cast a void* into a string* using standard C-style casts. Remember that a reference is not treated like a pointer when used, it's treated like a normal object. So if you're passing a value by reference to a function, you still have to de-refrence it to get its address.
However, as others have said, a better way to do this is with templates
static_cast<char*>(str.c_str())
looks odd to me. str.c_str() retrieves the C-like string, but with type const char *, and to convert to char * you'd normally use const_cast<char *>(str.c_str()). Except that that's not good to do, since you'd be meddling with the internals of a string. Are you sure you didn't get a warning on that?
You should be able to use static_cast<void *>(&str). The error message you got suggests to me that you got something else wrong, so if you could post the code we could look at it. (The data type std::string& is a reference to a string, not a pointer to one, so the error message is correct. What I don't know is how you got a reference instead of a pointer.)
And, yes, this is verbose. It's intended to be. Casting is usually considered a bad smell in a C++ program, and Stroustrup wanted casts to be easy to find. As has been discussed in other answers, the right way to build a data structure of arbitrary base type is by using templates, not casts and pointers.