Is it possible in ANY way to have a vector of type(def)s in C++11/14 ?
The first thing I tried was have a vector of a base class and somehow get the typedef from it's derived form but I can't get this to work whatever I try (not possible most likely).
Pseudo-C++:
class base
{
/* somehow access 'type' from derived */
}
template <typename T>
class derived : base
{
typedef T type;
}
vector<base*> vec;
vec.push_back( new derived<int> );
vec.push_back( new derived<double> );
vec.push_back( new derived<float> );
vec.push_back( new derived<string> );
for(auto& item : vec)
static_cast< item->type >( /* something */ );
Boost MPL provides a compile time construct for this, for example:
typedef boost::mpl::vector<int, double, std::string, CustomA, CustomB> seq_of_types;
You can interact with this at compile type using the extensive set of meta functions defined in mpl. There are also some run-time crossover functions too. The important point here is that this is a sequence of types, there are no instances of each type to interact with. Even the runtime functions only allow interacting with types.
Boost Fusion (and std::tuple) steps in here to provide a runtime heterogenous container, so for example
boost::fusion::vector<int, double, std::string> v{10, 100., "Foo"};
Now at compile time, you have access to the type information of each entry, and at runtime you have an instance of each type in the sequence to work with.
It could be possible that what you are trying to achieve could be done with plain inheritance without having to resort to the above, so the vector holds a pointer to base class, which has a virtual function which is overriden in the derived classes which does what you want. This is possibly the cleanest.
Alternatively, the same is possible, without resorting to using inheritance if you use a variadic type such as boost::variant, for example:
std::vector<boost::variant<int, double, std::string>> entries;
Now each entry is one of the types of int, double, std::string. Then as you iterate, you can use a static visitor to operate on the specific instance. I think I've answered a question on SO a while ago which demonstrates this.
So which will it be?
EDIT: base on your last comment, then the latter (variant) doesn't really fly, and nor does plain inheritance. I think a fusion vector is really not necessary either as you don't need an instance of each type. The most suitable thing for you then is the mpl::vector, and use the runtime function mpl::for_each
Maybe you could look into Loki's type lists (see here). There's a question on to use them here. I think this is as close as it gets to what you're looking for. Boost MPL also has something like that (see this question), with type lists and type vectors.
No, you can't. Types in C++ aren't objects, and they can't be used as values.
Depending what you actually need, you might be able to do something with type_info (or rather, pointers to them). This is not the type, and it can't be used to access the type, but it can be used for example in equality comparisons to determine whether two type_info objects refer to the same or different types.
Depends on what you mean by "vector"
A specialization of std::tuple is a (compile-time) ordered collection of types.
You can index them (untested code):
typedef std::tuple<int, long, void, std::string, std::complex<float> Tuple;
typename std::tuple_element<1, Tuple>::type foo; // foo is of type long
You can do all sorts of manipulations (at compile-time) on tuples, and the results of these manipulations are types (or other tuples). C++14 formalizes (but did not invent) the idea of "index sequences", which let you do pretty much arbitrary tuple-type -> tuple-type transforms.
Related
I'm trying to type erase an object and ran into a bit of an issue that I'm hoping someone here may be have expertise in.
I haven't had a problem type-erasing arbitrary non-templated functions; so far what I have been doing is creating a custom static
"virtual table"-esque collection of function pointers. This is all managed with non-capturing lambdas, since
they decay into free-function pointers:
template<typename Value, typename Key>
class VTable {
Value (*)(const void*, const Key&) at_function_ptr = nullptr;
// ...
template<typename T>
static void build_vtable( VTable* table ) {
// normalizes function into a simple 'Value (*)(const void*, const Key&)'' type
static const auto at_function = []( const void* p, const Key& key ) {
return static_cast<const T*>(p)->at(key);
}
// ...
table->at_function_ptr = +at_function;
}
// ...
}
(There are more helper functions/aliases that are omitted for brevity)
Sadly this same approach does not work with a function template.
My desire is for the type-erased class to have something akin to the following:
template<typename U>
U convert( const void* ptr )
{
return cast<U>( static_cast<const T*>( ptr ) );
}
where:
cast is a free function,
U is the type being casted to,
T is the underlying type erased type being casted from, and
ptr is the type-erased pointer that follows the same idiom above for the type erasure.
[Edit: The issue above is that T isn't known from the function convert; the only function that knows of T's type in the example is build_vtable. This may just require a design change]
The reason this has become challenging is that there does not appear to be any simple way to type erase both types
independently. The classical/idiomatic type-erasure technique of a base-class doesn't work here, since you can't have
a virtual template function. I have experimented with a visitor-like pattern with little success for similar
reasons to the above.
Does anyone with experience in type-erasure have any suggestions or techniques that can be used to achieve what
I'm trying to do? Preferably in standards-conforming c++14 code.
Or, perhaps is there design change that might facilitate the same concept desired here?
I've been searching around for this answer for a little while now, and haven't had much luck. There are a few cases that are similar to what I'm trying to do, but often with enough differences that the solutions don't seem to apply to the same problem (Please let me know if I'm wrong!).
It appears most readings/blogs on these topics tend to cover the basic type-erasure technique, but not what I'm looking for here!
Thanks!
Note: please do not recommend Boost. I am in an environment where I am unable to use their libraries, and do not
wish to introduce that dependency to the codebase.
Each distinct convert<U> is a distinct type erasure.
You can type erase a list of such functions, storing the method of doing it in each case. So suppose you have Us..., type erase all of convert<Us>....
If Us... is short this is easy.
If it is long, this is a pain.
It is possible that the majority of these may be null (as in operation is illegal), so you can implement a sparse vtable that takes this into account, so your vtable isn't large and full of zeros. This can be done by type erasing a function (using the standard vtable technique) that returns a reference (or a type-erased accessor) to said sparse vtable that maps from std::typeindex to U-placement-constructor converter (that writes to a void* in the signature). You then run that function, extract the entry, create a buffer to store the U in, call the U-placement-constructor converter passing in that buffer.
This all occurs in your type_erased_convert<U> function (which itself is not type-erased) so end users don't have to care about the internal details.
You know, simple.
The restriction is that the list of possible convert-to types U that are supported needs to be located prior to the location of type erasure. Personally, I would restrict type_erased_convert<U> to only being called on the same list of types U, and accept that this list must be fundamentally short.
Or you could create some other conversion graph that lets you plug a type into it and determine how to reach another type possibly through some common intermediary.
Or you could use a scripting or bytecode language that includes a full compiler during the execution phase, permitting the type-erased method to be compiled against a new completely independant type when called.
std::function< void(void const*, void*) > constructor;
std::function< constructor( std::typeindex ) > ctor_map;
template<class...Us>
struct type_list {};
using target_types = type_list<int, double, std::string>;
template<class T, class U>
constructor do_convert( std::false_type ) { return {}; }
template<class T, class U>
constructor do_convert( std::true_type ) {
return []( void const* tin, void* uout ) {
new(uout) U(cast<U>( static_cast<const T*>( ptr ) ));
};
}
template<class T, class...Us>
ctor_map get_ctor_map(std::type_list<Us...>) {
std::unordered_map< std::typeindex, constructor > retval;
using discard = int[];
(void)discard{0,(void(
can_convert<U(T)>{}?
(retval[typeid(U)] = do_convert<T,U>( can_convert<U(T)>{} )),0
: 0
),0)...};
return [retval]( std::typeindex index ) {
auto it = retval.find(index);
if (it == retval.end()) return {};
return it->second;
};
}
template<class T>
ctor_map get_ctor_map() {
return get_ctor_map<T>(target_types);
}
You can replace the unordered_map with a compact stack-based one when it is small. Note that std::function in MSVC is limited to about 64 bytes or so?
If you don't want a fixed list of source/dest types, we can decouple this.
Expose the typeindex of the type stored within the type erasure container, and the ability to get at the void const* that points at it.
Create a type trait that maps a type T to the list of types Us... it supports conversion-to. Use the above technique to store these conversion functions in a (global) map. (Note that this map can be placed in static storage, as you can deduce the size of the buffer required etc. But using an static unordered_map is easier).
Create a second type trait that maps a type U to a list of types Ts... it supports conversion-from.
In both cases, a function convert_construct( T const* src, tag_t<U>, void* dest ) is called to do the actual conversion.
You'd start with a set of universal targets type_list<int, std::string, whatever>. A particular type would augment it by having a new list.
For a type T building its sparse conversion table we would attempt each target type. If an overload of convert_construct fails to be found, the map would not be populated for that case. (Generating compile time errors for types added explicitly to work with T is an option).
On the other end, when we call the type_erased_convert_to<U>( from ), we look for a different table that maps the type U cross typeindex to a U(*)(void const* src) converter. Both the from-T map gotten from the type-erased T and the to-U gotten in the wrapping code are consulted to find a converter.
Now, this doesn't permit certain kinds of conversion. For example, a type T that converts-from anything with a .data() -> U* and .size() -> size_t method needs to explicitly list every type it converts-from.
The next step would be to admit a multi-step conversion. A multi-step conversion is where you teach your T to convert-to some (set of) famous types, and we teach U to convert-from a similar (set of) famous types. (The fame of these types is optional, I'll admit; all you need to know is how to create and destroy them, what storage you need, and a way to match up the T-to and U-from options, to use them as an intermediary.)
This may seem over engineered. But the ability to convert-to std::int64_t and convert-from that to any signed integral type is an example of this (and similarly for uint64_t and unsigned).
Or the ability to convert-to a dictionary of key-value pairs, and then examine this dictionary on the other side to determine if we can convert-from it.
As you go down this path, you'll want to examine loose typing systems in various scripting and bytecode languages to pick up how they did it.
In my variable data, when running "add a variable" script code, how to define a generic container for all types? And what is the generic formula to access them? It's annoying because I have to define a vector template for each type (int float double etc). My variable should contain only and only a generic vector object, whatever it's int, or float or double etc. Is it possible? Any idea?
That's the whole point of the Standard Template Library..
std::vector<int>
std::vector<float>
Two vectors - the same class, templated with different types.
If you want a container of differing type you might want to look at std::tuple
If you want a single vector that contains objects of many different types, then you might want to use boost::any, or possibly boost::variant.
Edit:
oh, you want a container that can fit in any type? Yes you can. But within certain restrictions.
See boost::any and boost::variant. boost::variant would enable you to save data of several types enumerated when declaring the boost::variant. boost::any doesn't make you enumerate all types you want to support, but you need to cast them to get back the value yourself.
In short, you must either store the type information somewhere else ( when using boost::any ), or just support a few types (say, a heterogeneous vector that supports int and double using boost::variant)
template in C++ works exactly by eliminating the need to write the same class for every type.
For example:
// function template
template <class T>
T GetMax (T a, T b) {
T result;
result = (a>b)? a : b;
return (result);
}
this GetMax should work for whatever type that has a > operator. So that is exactly what template is for in C++.
If you need more help on implementing a vector on C++ (which, by the way, is not so simple when it comes to custom types that has its own constructor and destructor. You may need allocator to get un-initialized space), read this (Implementation of Vector in C++).
Is there a C++ standard type for holding a vector having a constant size? For example, something like a tuple with all element types being the same, so I only have to provide the size as a template argument?
I would like to have the same/similar behavior as when using std::vector, but the type should be as compact and efficient as a raw array (so no dynamic allocation, no run-time size information, etc.)
I prefer a C++03-compatible solution, so reusing a std::tuple isn't what I want.
Does the following class do what I want?
template<typename T, int N>
struct vec
{
T component[N];
// (+ some logic and accessors like operator[]...)
};
// concrete example:
vec<int,3> myVector;
Does it really differ from just saying T myVector[N] (concrete example int myVector[3])? Because that's what I am currently doing but I'm experiencing a couple of problems, since raw arrays are "just pointers" (+ size information) and can't be used as return values as well as aren't really passed by value (no deep copy occures).
C++11 has std::array; which is basically the same as you wrote.
For C++03, use boost::array which is basically compatible to std::array.
I want to map pointer to integer for purpose of serialization. The pointers may be of different types and may point to polymorphic objects possibly using multiple inheritance. I need to query the map to know if the pointer is stored in it and if it is, then what is the associated integral value.
What is the correct way to do it?
The simple way of map<void*, int> that I thought of would not work because operator < is not defined for arbitrary pointers. Or is that not a problem on common systems?
Another solution would be to have a vector<void*>. But this would require to loop over all pointers stored in and I am not sure if the casting to void * would not break the operator == for objects using inheritance.
You are in luck with your initial idea of using map<void*, int>.
Although you are right that operator< is not defined for pointers, the predicate used by std::map<> is std::less<> and the C++ standard requires that std::less<T*> also works for arbitrary pointers.
Quote from the C++ standard to support this ([lib.comparisons]/8):
For templates greater, less, greater_equal, and less_equal, the specializations for any pointer type yield a total order, even if the built-in operators <, >, <=, >= do not.
Why don't you simply introduce a dummy base class for all of your serializable classes ?
class Serializable
{
};
map< Serializable *, int > integralMap;
you could just do a map of unsigned int32/64 to int (depending on x86 or x64). Just cast the void* to the unsigned int and it'll happily do the comparison.
Have a look at these:
http://en.wikipedia.org/wiki/Pointer_(computing)#C_and_C.2B.2B
http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/BitOp/pointer.html
I am writing a COM wrapper for a COM object that sends different types of values from a client and want to map these types in a Map to their actual C++ type, such as VT_BSTR to a wstring, etc.
I was thinking of defining an enumuration of all COM Variant types and then using a map to have that Enum as the key and the actual type containing the retrieved value, however I'm running into the issue that I cannot seem to find a global type to put in my map that I can cast to a string or double or whatever is handed to me to place in the map.
Perhaps my thinking of how to do this is entirely wrong, please advice?
I was thinking of a void pointer, however it seems the compiler doesn't like my casts:
(example)
enum Type
{
VT_INTEGER=0,
VT_DBL=1
};
map<Type, void*> typemap;
typedef pair<Type, void*> m_typepair;
typemap.insert( m_typepair(VT_INTEGER, 0));
typemap.insert( m_typepair(VT_DBL, (double)2.5)); // it does not like this cast
map<Type, void*>::iterator m_typeiter;
Iterating this map would probably need a switch statement inside to find the right type, I'm not sure if there is a better way?
Not sure what you're trying to do, it certainly sounds wrong. A VARIANT you get from a client needs to be converted to the type that you know how to deal with. That's easy to do, just call the VariantToXxxx() function. For example, use VariantToString() if you want to get a string.
There are several C++ wrapper classes already available that make this easier. _variant_t, CComVariant, COleVariant. They all do the same thing, just different #include files. _variant_t is a good one because it doesn't tie you into either MFC or ATL. Unless you are already using them. Their ChangeType() method makes the conversion. Memory management is automatic.
I usually use template specialization for this kind of tasks. I have a template function that converts from a variant type to a C++ type that looks like this:
template <typename T>
T variantToCpp(const Variant&);
template <>
int variantToCpp<int>(const Variant& v)
{
// Check that v really contains an int, if not, you can silently fail or throw an exception
// Get and return the int
}
template <>
std::wstring variantToCpp<std::wstring>(const Variant& v)
{
// Check that v really contains a string, if not, you can silently fail or throw an exception
// Get and return the string
}
// etc. for each C++ type
// Usage
int i = variantToCpp<int>(someVariantIGotViaCOM);
This way you get a constant-time conversion from a Variant to a C++ type. Also note that the default templated function has no body - it will cause a linker error (on most compilers) if someone tries to use a conversion for an unspecialized type.
Similarly you can do the conversion from a C++ type to a Variant:
template <typename T>
Variant cppToVariant(T);
template <>
Variant cppToVariant<int>(int val)
{
// Convert to variant and return it
}
// etc. for each type
// Usage:
int i = 10;
Variant var = cppToVariant(i); // You don't even need to explicitly specify the type here, the compiler deduces it
If you insist on using a map and tons of ifs for this kind of conversion, you can use your void* pointer, you just have to initialize it with a pointer to the type:
int *myInteger = new int; *myInteger = 42;
double *myDouble = new double; *myDouble = 42;
typemap.insert( m_typepair(VT_INTEGER, myInteger));
typemap.insert( m_typepair(VT_DBL, myDouble));
// Don't forget to free them when you clear the map
If you aren't satisfied with any of the above solutions, boost::any might be worth looking at.
Are you aware of _variant_t ? You might be reinventing the wheel. It has all the relevant constrcutors and overloaded assignment. I.e. _variant_t var = 0.0 works as expected (VT_R8)